From 3c61222d68e192e3c3908f45749aacfb591a169a Mon Sep 17 00:00:00 2001 From: Philip Mueller Date: Thu, 22 Feb 2024 14:10:07 -0500 Subject: [PATCH 001/147] [ruby/prism] all constant nodes should have full_name and full_name_parts methods https://github.com/ruby/prism/commit/792265ae0b --- lib/prism/node_ext.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 8b92fe1feef3e8..12567b8abfaab7 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -98,6 +98,19 @@ def full_name end end + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + def full_name_parts + [name] + end + + # Returns the full name of this constant. For example: "Foo" + def full_name + name.to_s + end + end + class ConstantPathNode < Node # An error class raised when dynamic parts are found while computing a # constant path's full name. For example: From 2b0bc447e5b4057253f7cb8480fc6338f6528858 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 14:32:52 -0800 Subject: [PATCH 002/147] Remove unused matrix.configure from macos.yml --- .github/workflows/macos.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 0f96e5894b3459..eb56f1c9bf1a86 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,7 +25,6 @@ jobs: strategy: matrix: test_task: ['check'] - configure: [''] os: ${{ fromJSON(format('["macos-12","macos-13"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }} include: - test_task: test-all TESTS=--repeat-count=2 @@ -64,7 +63,7 @@ jobs: dummy-files: ${{ matrix.test_task == 'check' }} - name: Run configure - run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + run: ../src/configure -C --disable-install-doc - run: make prepare-gems if: ${{ matrix.test_task == 'test-bundled-gems' }} @@ -99,7 +98,7 @@ jobs: - uses: ./.github/actions/slack with: - label: ${{ matrix.os }} / ${{ matrix.test_task }} ${{ matrix.configure }} + label: ${{ matrix.os }} / ${{ matrix.test_task }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot if: ${{ failure() }} From bccf4b30fa251dd4394d4ad477bad53c624d2aba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 14:34:19 -0800 Subject: [PATCH 003/147] Skip under_gc_compact_stress on s390x (#10073) --- test/ruby/test_array.rb | 1 + test/ruby/test_enumerator.rb | 2 ++ test/ruby/test_exception.rb | 1 + test/ruby/test_method.rb | 1 + test/ruby/test_regexp.rb | 3 +++ test/ruby/test_string.rb | 5 +++++ test/ruby/test_symbol.rb | 1 + test/ruby/test_weakkeymap.rb | 1 + test/ruby/test_weakmap.rb | 1 + tool/lib/envutil.rb | 1 + 10 files changed, 17 insertions(+) diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 97e2fa3de85883..e40651eb8e5f81 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -1703,6 +1703,7 @@ def test_slice_out_of_range end def test_slice_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) } EnvUtil.under_gc_compact_stress do a = [0, 1, 2, 3, 4, 5] diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index 11cfe69864d865..825c191d874c81 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -128,6 +128,7 @@ def test_with_index end def test_with_index_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do assert_equal([[1, 0], [2, 1], [3, 2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a) assert_equal([[1, 5], [2, 6], [3, 7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a) @@ -863,6 +864,7 @@ def test_lazy_chain end def test_lazy_chain_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do ea = (10..).lazy.select(&:even?).take(10) ed = (20..).lazy.select(&:odd?) diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index c5f7a94a77a6a8..09a6541e904edc 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -1468,6 +1468,7 @@ def test_detailed_message end def test_detailed_message_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do e = RuntimeError.new("foo\nbar\nbaz") assert_equal("foo (RuntimeError)\nbar\nbaz", e.detailed_message) diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index e563e53cd56e18..ec06f4c50a150d 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -451,6 +451,7 @@ def m.bar; :bar; end end def test_clone_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do o = Object.new def o.foo; :foo; end diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 9eab99d6773437..c996b1785acae8 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -73,6 +73,7 @@ def test_to_s end def test_to_s_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do str = "abcd\u3042" [:UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE].each do |es| @@ -470,6 +471,7 @@ def test_inspect end def test_inspect_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do assert_equal('/(?-mix:\\/)|/', Regexp.union(/\//, "").inspect) end @@ -891,6 +893,7 @@ def test_match end def test_match_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do m = /(?.)(?[^aeiou])?(?.+)/.match("hoge\u3042") assert_equal("h", m.match(:foo)) diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 85a72b09ccfeda..149c128ed40bbf 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -909,6 +909,7 @@ def test_undump end def test_undump_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 a = S("Test") << 1 << 2 << 3 << 9 << 13 << 10 EnvUtil.under_gc_compact_stress do assert_equal(a, S('"Test\\x01\\x02\\x03\\t\\r\\n"').undump) @@ -1284,6 +1285,7 @@ def test_gsub end def test_gsub_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal(S("hll"), S("hello").gsub(/([aeiou])/, S('<\1>'))) } end @@ -1331,6 +1333,7 @@ def test_gsub! end def test_gsub_bang_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do a = S("hello") a.gsub!(/([aeiou])/, S('<\1>')) @@ -1672,6 +1675,7 @@ def test_scan end def test_scan_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { assert_equal([["1a"], ["2b"], ["3c"]], S("1a2b3c").scan(/(\d.)/)) } end @@ -2103,6 +2107,7 @@ def o.to_s; self; end end def test_sub_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do m = /&(?.*?);/.match(S("aaa & yyy")) assert_equal("amp", m["foo"]) diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 7f75ecd90e8361..67a8303c5470be 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -119,6 +119,7 @@ def test_inspect end def test_inspect_under_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress do assert_inspect_evaled(':testing') end diff --git a/test/ruby/test_weakkeymap.rb b/test/ruby/test_weakkeymap.rb index 7907bf889fc617..6b3ffbb81f5bb5 100644 --- a/test/ruby/test_weakkeymap.rb +++ b/test/ruby/test_weakkeymap.rb @@ -124,6 +124,7 @@ def test_compaction end def test_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { ObjectSpace::WeakKeyMap.new } end diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb index 0371afa77a03de..97d7197dbbe2d4 100644 --- a/test/ruby/test_weakmap.rb +++ b/test/ruby/test_weakmap.rb @@ -238,6 +238,7 @@ def test_compaction end def test_gc_compact_stress + omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 EnvUtil.under_gc_compact_stress { ObjectSpace::WeakMap.new } end diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb index b5dcfb9d043f88..a2ddf74052a842 100644 --- a/tool/lib/envutil.rb +++ b/tool/lib/envutil.rb @@ -251,6 +251,7 @@ def under_gc_stress(stress = true) module_function :under_gc_stress def under_gc_compact_stress(val = :empty, &block) + raise "compaction doesn't work well on s390x. Omit the test in the caller." if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 auto_compact = GC.auto_compact GC.auto_compact = val under_gc_stress(&block) From cdca94208f18b0921340906a1cb43f88737539e2 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 15:15:03 -0800 Subject: [PATCH 004/147] Fallback every macos-arm-oss usage to macos-14 (#10074) --- .github/workflows/codeql-analysis.yml | 7 +++---- .github/workflows/macos.yml | 9 ++++++--- .github/workflows/yjit-macos.yml | 5 ++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c698f85ecb851e..dbb94baae13742 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,8 +39,7 @@ jobs: security-events: write # for github/codeql-action/autobuild to send a status report # CodeQL fails to run pull requests from dependabot due to missing write access to upload results. if: >- - ${{github.repository == 'ruby/ruby' && - !(false + ${{!(false || contains(github.event.head_commit.message, '[DOC]') || contains(github.event.pull_request.title, '[DOC]') || contains(github.event.pull_request.labels.*.name, 'Documentation') @@ -58,14 +57,14 @@ jobs: os: ubuntu-latest # ruby analysis used large memory. We need to use a larger runner. - language: ruby - os: macos-arm-oss + os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} steps: - name: Checkout repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install libraries - if: ${{ matrix.os == 'macos-arm-oss' }} + if: ${{ contains(matrix.os, 'macos') }} uses: ./.github/actions/setup/macos - name: Install libraries diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index eb56f1c9bf1a86..1f2b4ef585b9b3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,12 +25,15 @@ jobs: strategy: matrix: test_task: ['check'] - os: ${{ fromJSON(format('["macos-12","macos-13"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }} + os: + - macos-12 + - macos-13 + - ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} include: - test_task: test-all TESTS=--repeat-count=2 - os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-13' }} + os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} - test_task: test-bundled-gems - os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-13' }} + os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} fail-fast: false env: diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index c2a6ca04f05c5d..de585e558da0a5 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -24,11 +24,10 @@ jobs: cargo: name: cargo test - runs-on: macos-arm-oss + runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} if: >- - ${{github.repository == 'ruby/ruby' && - !(false + ${{!(false || contains(github.event.head_commit.message, '[DOC]') || contains(github.event.pull_request.title, '[DOC]') || contains(github.event.pull_request.labels.*.name, 'Documentation') From 38bf622cdc9d2b338156e3bfe75858e26acd9e49 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 15:28:46 -0800 Subject: [PATCH 005/147] Fix -Wmaybe-uninitialized on Complex#** (#10075) --- complex.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/complex.c b/complex.c index c550c2a57b54e2..28d5b2058b74be 100644 --- a/complex.c +++ b/complex.c @@ -1065,6 +1065,8 @@ complex_pow_for_special_angle(VALUE self, VALUE other) else if (f_eqeq_p(dat->real, f_negate(dat->imag))) { x = dat->imag; dir = 3; + } else { + dir = 0; } if (UNDEF_P(x)) return x; From d5080f6e8b77364483ff6727b1065e45e180f05d Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 16:11:24 -0800 Subject: [PATCH 006/147] Fix -Wsign-compare on String#initialize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../string.c:1886:57: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘long int’ [-Wsign-compare] 1886 | if (STR_EMBED_P(str)) RUBY_ASSERT(osize <= str_embed_capa(str)); | ^~ --- string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/string.c b/string.c index a4ba85f42e2a07..f8a64fca13c5e9 100644 --- a/string.c +++ b/string.c @@ -1883,7 +1883,7 @@ rb_str_init(int argc, VALUE *argv, VALUE str) const char *const old_ptr = RSTRING_PTR(str); const size_t osize = RSTRING_LEN(str) + TERM_LEN(str); char *new_ptr = ALLOC_N(char, size); - if (STR_EMBED_P(str)) RUBY_ASSERT(osize <= str_embed_capa(str)); + if (STR_EMBED_P(str)) RUBY_ASSERT((long)osize <= str_embed_capa(str)); memcpy(new_ptr, old_ptr, osize < size ? osize : size); FL_UNSET_RAW(str, STR_SHARED|STR_NOFREE); RSTRING(str)->as.heap.ptr = new_ptr; From 3ca6da24e397e550d589a69791be7697c0cb73c6 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 23 Feb 2024 09:30:14 +0900 Subject: [PATCH 007/147] [Bug #20295] Fix SEGV when parsing invalid regexp --- parse.y | 10 ++++++---- test/ruby/test_syntax.rb | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/parse.y b/parse.y index c753dec91f3d22..1631bdecc2bf36 100644 --- a/parse.y +++ b/parse.y @@ -13017,10 +13017,12 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo case NODE_REGX: { const VALUE lit = rb_node_regx_string_val(n); - NODE *match = NEW_MATCH2(node1, node2, loc); - RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc); - nd_set_line(match, line); - return match; + if (!NIL_P(lit)) { + NODE *match = NEW_MATCH2(node1, node2, loc); + RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc); + nd_set_line(match, line); + return match; + } } } } diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index d49482038826fd..42108f955f0241 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1034,6 +1034,14 @@ def test_heredoc_mixed_encoding assert_not_match(/end-of-input/, e.message) end + def test_invalid_regexp + bug20295 = '[ruby-core:116913] [Bug #20295]' + + assert_syntax_error("/[/=~s", /premature end of char-class/, bug20295) + assert_syntax_error("/(?<>)/=~s", /group name is empty/, bug20295) + assert_syntax_error("/(?[)/=~s", /premature end of char-class/, bug20295) + end + def test_lineno_operation_brace_block expected = __LINE__ + 1 actual = caller_lineno\ From 548151d1e9f64913e26acec61e95d0568da35e5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 03:00:12 +0000 Subject: [PATCH 008/147] Bump github/codeql-action from 3.24.3 to 3.24.4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.3 to 3.24.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/379614612a29c9e28f31f39a59013eb8012a51f0...e2e140ad1441662206e8f97754b166877dfa1c73) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/scorecards.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index dbb94baae13742..054d7abee2b039 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -78,15 +78,15 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/init@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/autobuild@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/analyze@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 with: category: '/language:${{ matrix.language }}' upload: False @@ -116,7 +116,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/upload-sarif@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 69e31c8ad95f66..d409905875424c 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@379614612a29c9e28f31f39a59013eb8012a51f0 # v2.1.27 + uses: github/codeql-action/upload-sarif@e2e140ad1441662206e8f97754b166877dfa1c73 # v2.1.27 with: sarif_file: results.sarif From ff6ebba9deccd4d7514d416ea4910de7717194cd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 15 Dec 2023 14:20:58 -0500 Subject: [PATCH 009/147] [ruby/prism] Parse numeric values https://github.com/ruby/prism/commit/a6a552411c --- prism/extension.c | 29 ++++++ prism/prism.h | 1 + prism/util/pm_number.c | 164 ++++++++++++++++++++++++++++++++ prism/util/pm_number.h | 95 ++++++++++++++++++ test/prism/number_parse_test.rb | 36 +++++++ 5 files changed, 325 insertions(+) create mode 100644 prism/util/pm_number.c create mode 100644 prism/util/pm_number.h create mode 100644 test/prism/number_parse_test.rb diff --git a/prism/extension.c b/prism/extension.c index cb7d3a5e6a3096..4af28bdb9672b4 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -949,6 +949,34 @@ named_captures(VALUE self, VALUE source) { return names; } +/** + * call-seq: + * Debug::number_parse(source) -> Integer + * + * Parses the given source string and returns the number it represents. + */ +static VALUE +number_parse(VALUE self, VALUE source) { + const uint8_t *start = (const uint8_t *) RSTRING_PTR(source); + size_t length = RSTRING_LEN(source); + + pm_number_t number = { 0 }; + pm_number_parse(&number, PM_NUMBER_BASE_UNKNOWN, start, start + length); + + VALUE result = UINT2NUM(number.head.value); + size_t shift = 0; + + for (pm_number_node_t *node = number.head.next; node != NULL; node = node->next) { + VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); + result = rb_funcall(receiver, rb_intern("|"), 1, result); + } + + if (number.negative) result = rb_funcall(result, rb_intern("-@"), 0); + pm_number_free(&number); + + return result; +} + /** * call-seq: * Debug::memsize(source) -> { length: xx, memsize: xx, node_count: xx } @@ -1148,6 +1176,7 @@ Init_prism(void) { // internal tasks. We expose these to make them easier to test. VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug"); rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1); + rb_define_singleton_method(rb_cPrismDebug, "number_parse", number_parse, 1); rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1); rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); diff --git a/prism/prism.h b/prism/prism.h index ffc722e90c48a6..88eb128769225d 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -10,6 +10,7 @@ #include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" #include "prism/util/pm_memchr.h" +#include "prism/util/pm_number.h" #include "prism/util/pm_strncasecmp.h" #include "prism/util/pm_strpbrk.h" #include "prism/ast.h" diff --git a/prism/util/pm_number.c b/prism/util/pm_number.c new file mode 100644 index 00000000000000..d2733330a64cc6 --- /dev/null +++ b/prism/util/pm_number.c @@ -0,0 +1,164 @@ +#include "prism/util/pm_number.h" + +/** + * Create a new node for a number in the linked list. + */ +static pm_number_node_t * +pm_number_node_create(pm_number_t *number, uint32_t value) { + number->length++; + pm_number_node_t *node = malloc(sizeof(pm_number_node_t)); + *node = (pm_number_node_t) { .next = NULL, .value = value }; + return node; +} + +/** + * Add a 32-bit integer to a number. + */ +static void +pm_number_add(pm_number_t *number, uint32_t addend) { + uint32_t carry = addend; + pm_number_node_t *current = &number->head; + + while (carry > 0) { + uint64_t result = (uint64_t) current->value + carry; + carry = (uint32_t) (result >> 32); + current->value = (uint32_t) result; + + if (carry > 0) { + if (current->next == NULL) { + current->next = pm_number_node_create(number, carry); + break; + } + + current = current->next; + } + } +} + +/** + * Multiple a number by a 32-bit integer. In practice, the multiplier is the + * base of the number, so this is 2, 8, 10, or 16. + */ +static void +pm_number_multiply(pm_number_t *number, uint32_t multiplier) { + uint32_t carry = 0; + + for (pm_number_node_t *current = &number->head; current != NULL; current = current->next) { + uint64_t result = (uint64_t) current->value * multiplier + carry; + carry = (uint32_t) (result >> 32); + current->value = (uint32_t) result; + + if (carry > 0 && current->next == NULL) { + current->next = pm_number_node_create(number, carry); + break; + } + } +} + +/** + * Return the value of a digit in a number. + */ +static uint32_t +pm_number_parse_digit(const uint8_t character) { + switch (character) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: assert(false && "unreachable"); + } +} + +/** + * Parse a number from a string. This assumes that the format of the number has + * already been validated, as internal validation checks are not performed here. + */ +PRISM_EXPORTED_FUNCTION void +pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end) { + switch (*start) { + case '-': + number->negative = true; + /* fallthrough */ + case '+': + start++; + break; + default: + break; + } + + uint32_t multiplier; + switch (base) { + case PM_NUMBER_BASE_BINARY: + start += 2; // 0b + multiplier = 2; + break; + case PM_NUMBER_BASE_OCTAL: + start++; // 0 + if (*start == 'o' || *start == 'O') start++; // o + multiplier = 8; + break; + case PM_NUMBER_BASE_DECIMAL: + if (*start == '0' && (end - start) > 1) start += 2; // 0d + multiplier = 10; + break; + case PM_NUMBER_BASE_HEXADECIMAL: + start += 2; // 0x + multiplier = 16; + break; + case PM_NUMBER_BASE_UNKNOWN: + if (*start == '0' && (end - start) > 1) { + switch (start[1]) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': start++; multiplier = 8; break; + case 'b': case 'B': start += 2; multiplier = 2; break; + case 'o': case 'O': start += 2; multiplier = 8; break; + case 'd': case 'D': start += 2; multiplier = 10; break; + case 'x': case 'X': start += 2; multiplier = 16; break; + default: assert(false && "unreachable"); + } + } else { + multiplier = 10; + } + break; + } + + for (pm_number_add(number, pm_number_parse_digit(*start++)); start < end; start++) { + if (*start == '_') continue; + pm_number_multiply(number, multiplier); + pm_number_add(number, pm_number_parse_digit(*start)); + } +} + +/** + * Recursively destroy the linked list of a number. + */ +static void +pm_number_node_destroy(pm_number_node_t *number) { + if (number->next != NULL) { + pm_number_node_destroy(number->next); + } + + free(number); +} + +/** + * Free the internal memory of a number. This memory will only be allocated if + * the number exceeds the size of a single node in the linked list. + */ +PRISM_EXPORTED_FUNCTION void +pm_number_free(pm_number_t *number) { + if (number->head.next) { + pm_number_node_destroy(number->head.next); + } +} diff --git a/prism/util/pm_number.h b/prism/util/pm_number.h new file mode 100644 index 00000000000000..c2507cf1df42ca --- /dev/null +++ b/prism/util/pm_number.h @@ -0,0 +1,95 @@ +/** + * @file pm_number.h + * + * This module provides functions for working with arbitrary-sized numbers. + */ +#ifndef PRISM_NUMBER_H +#define PRISM_NUMBER_H + +#include "prism/defines.h" + +#include +#include +#include +#include + +/** + * A node in the linked list of a pm_number_t. + */ +typedef struct pm_number_node { + /** A pointer to the next node in the list. */ + struct pm_number_node *next; + + /** The value of the node. */ + uint32_t value; +} pm_number_node_t; + +/** + * This structure represents an arbitrary-sized number. It is implemented as a + * linked list of 32-bit integers, with the least significant digit at the head + * of the list. + */ +typedef struct { + /** + * The head of the linked list, embedded directly so that allocations do not + * need to be performed for small numbers. + */ + pm_number_node_t head; + + /** The number of nodes in the linked list that have been allocated. */ + size_t length; + + /** + * Whether or not the number is negative. It is stored this way so that a + * zeroed pm_number_t is always positive zero. + */ + bool negative; +} pm_number_t; + +/** + * An enum controlling the base of a number. It is expected that the base is + * already known before parsing the number, even though it could be derived from + * the string itself. + */ +typedef enum { + /** The binary base, indicated by a 0b or 0B prefix. */ + PM_NUMBER_BASE_BINARY, + + /** The octal base, indicated by a 0, 0o, or 0O prefix. */ + PM_NUMBER_BASE_OCTAL, + + /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ + PM_NUMBER_BASE_DECIMAL, + + /** The hexidecimal base, indicated by a 0x or 0X prefix. */ + PM_NUMBER_BASE_HEXADECIMAL, + + /** + * An unknown base, in which case pm_number_parse will derive it based on + * the content of the string. This is less efficient and does more + * comparisons, so if callers know the base ahead of time, they should use + * that instead. + */ + PM_NUMBER_BASE_UNKNOWN +} pm_number_base_t; + +/** + * Parse a number from a string. This assumes that the format of the number has + * already been validated, as internal validation checks are not performed here. + * + * @param number The number to parse into. + * @param base The base of the number. + * @param start The start of the string. + * @param end The end of the string. + */ +PRISM_EXPORTED_FUNCTION void pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end); + +/** + * Free the internal memory of a number. This memory will only be allocated if + * the number exceeds the size of a single node in the linked list. + * + * @param number The number to free. + */ +PRISM_EXPORTED_FUNCTION void pm_number_free(pm_number_t *number); + +#endif diff --git a/test/prism/number_parse_test.rb b/test/prism/number_parse_test.rb new file mode 100644 index 00000000000000..401aead243fb20 --- /dev/null +++ b/test/prism/number_parse_test.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +return if Prism::BACKEND == :FFI + +module Prism + class NumberParseTest < TestCase + def test_number_parse + assert_number_parse(1) + assert_number_parse(50) + assert_number_parse(100) + assert_number_parse(100, "1_0_0") + + assert_number_parse(10, "0b1010") + assert_number_parse(10, "0B1010") + assert_number_parse(10, "0o12") + assert_number_parse(10, "0O12") + assert_number_parse(10, "012") + assert_number_parse(10, "0d10") + assert_number_parse(10, "0D10") + assert_number_parse(10, "0xA") + assert_number_parse(10, "0XA") + + assert_number_parse(2**32) + assert_number_parse(2**64 + 2**32) + assert_number_parse(2**128 + 2**64 + 2**32) + end + + private + + def assert_number_parse(expected, source = expected.to_s) + assert_equal expected, Debug.number_parse(source) + end + end +end From af0a6ea1d5253379bd634b41ed95d8e9feed8b44 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 22 Feb 2024 10:55:29 -0500 Subject: [PATCH 010/147] [ruby/prism] Add an IntegerField for parsing integer values https://github.com/ruby/prism/commit/120d8c0479 --- lib/prism/node_ext.rb | 7 ---- prism/config.yml | 3 ++ prism/extension.h | 6 +-- prism/prism.c | 26 +++++++++--- prism/templates/ext/prism/api_node.c.erb | 42 +++++++++++++++----- prism/templates/include/prism/ast.h.erb | 1 + prism/templates/lib/prism/dot_visitor.rb.erb | 2 +- prism/templates/lib/prism/dsl.rb.erb | 3 +- prism/templates/lib/prism/node.rb.erb | 2 +- prism/templates/lib/prism/serialize.rb.erb | 13 ++++++ prism/templates/src/node.c.erb | 41 ++++++++++++++----- prism/templates/src/prettyprint.c.erb | 30 ++++++++++++++ prism/templates/src/serialize.c.erb | 14 ++++++- prism/templates/template.rb | 17 ++++++++ prism/util/pm_number.c | 32 ++++++++++----- prism/util/pm_number.h | 8 ++++ test/prism/errors_test.rb | 8 ++-- 17 files changed, 199 insertions(+), 56 deletions(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 12567b8abfaab7..a9a0115a09d890 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -71,13 +71,6 @@ def value end end - class IntegerNode < Node - # Returns the value of the node as a Ruby Integer. - def value - Integer(slice) - end - end - class RationalNode < Node # Returns the value of the node as a Ruby Rational. def value diff --git a/prism/config.yml b/prism/config.yml index 15b7d4d0e9fd0a..33abcc623c0f11 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1867,6 +1867,9 @@ nodes: - name: flags type: flags kind: IntegerBaseFlags + - name: value + type: integer + comment: The value of the integer literal as a number. comment: | Represents an integer number literal. diff --git a/prism/extension.h b/prism/extension.h index 048f4b427f142e..6e5a3450122a93 100644 --- a/prism/extension.h +++ b/prism/extension.h @@ -7,9 +7,9 @@ #include #include "prism.h" -VALUE pm_source_new(pm_parser_t *parser, rb_encoding *encoding); -VALUE pm_token_new(pm_parser_t *parser, pm_token_t *token, rb_encoding *encoding, VALUE source); -VALUE pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE source); +VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding); +VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source); +VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source); void Init_prism_api_node(void); void Init_prism_pack(void); diff --git a/prism/prism.c b/prism/prism.c index cf893c6eef82ad..a1b2bf74e28816 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3803,12 +3803,25 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token assert(token->type == PM_TOKEN_INTEGER); pm_integer_node_t *node = PM_ALLOC_NODE(parser, pm_integer_node_t); - *node = (pm_integer_node_t) {{ - .type = PM_INTEGER_NODE, - .flags = base | PM_NODE_FLAG_STATIC_LITERAL, - .location = PM_LOCATION_TOKEN_VALUE(token) - }}; + *node = (pm_integer_node_t) { + { + .type = PM_INTEGER_NODE, + .flags = base | PM_NODE_FLAG_STATIC_LITERAL, + .location = PM_LOCATION_TOKEN_VALUE(token) + }, + .value = { 0 } + }; + + pm_number_base_t number_base; + switch (base) { + case PM_INTEGER_BASE_FLAGS_BINARY: number_base = PM_NUMBER_BASE_BINARY; break; + case PM_INTEGER_BASE_FLAGS_OCTAL: number_base = PM_NUMBER_BASE_OCTAL; break; + case PM_INTEGER_BASE_FLAGS_DECIMAL: number_base = PM_NUMBER_BASE_DECIMAL; break; + case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: number_base = PM_NUMBER_BASE_HEXADECIMAL; break; + default: assert(false && "unreachable"); + } + pm_number_parse(&node->value, number_base, token->start, token->end); return node; } @@ -14281,6 +14294,9 @@ static inline void parse_negative_numeric(pm_node_t *node) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: + node->location.start--; + ((pm_integer_node_t *) node)->value.negative = true; + break; case PM_FLOAT_NODE: node->location.start--; break; diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb index 55867f078cec4b..38288918d8bcce 100644 --- a/prism/templates/ext/prism/api_node.c.erb +++ b/prism/templates/ext/prism/api_node.c.erb @@ -12,13 +12,13 @@ static VALUE rb_cPrism<%= node.name %>; <%- end -%> static VALUE -pm_location_new(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { +pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start))); return ULL2NUM(value); } VALUE -pm_token_new(pm_parser_t *parser, pm_token_t *token, rb_encoding *encoding, VALUE source) { +pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source) { ID type = rb_intern(pm_token_type_name(token->type)); VALUE location = pm_location_new(parser, token->start, token->end); @@ -33,13 +33,30 @@ pm_token_new(pm_parser_t *parser, pm_token_t *token, rb_encoding *encoding, VALU } static VALUE -pm_string_new(pm_string_t *string, rb_encoding *encoding) { +pm_string_new(const pm_string_t *string, rb_encoding *encoding) { return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding); } +static VALUE +pm_integer_new(const pm_number_t *number) { + VALUE result = UINT2NUM(number->head.value); + size_t shift = 0; + + for (const pm_number_node_t *node = number->head.next; node != NULL; node = node->next) { + VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); + result = rb_funcall(receiver, rb_intern("|"), 1, result); + } + + if (number->negative) { + result = rb_funcall(result, rb_intern("-@"), 0); + } + + return result; +} + // Create a Prism::Source object from the given parser, after pm_parse() was called. VALUE -pm_source_new(pm_parser_t *parser, rb_encoding *encoding) { +pm_source_new(const pm_parser_t *parser, rb_encoding *encoding) { VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding); VALUE offsets = rb_ary_new_capa(parser->newline_list.size); @@ -53,12 +70,12 @@ pm_source_new(pm_parser_t *parser, rb_encoding *encoding) { typedef struct pm_node_stack_node { struct pm_node_stack_node *prev; - pm_node_t *visit; + const pm_node_t *visit; bool visited; } pm_node_stack_node_t; static void -pm_node_stack_push(pm_node_stack_node_t **stack, pm_node_t *visit) { +pm_node_stack_push(pm_node_stack_node_t **stack, const pm_node_t *visit) { pm_node_stack_node_t *node = malloc(sizeof(pm_node_stack_node_t)); node->prev = *stack; node->visit = visit; @@ -66,10 +83,10 @@ pm_node_stack_push(pm_node_stack_node_t **stack, pm_node_t *visit) { *stack = node; } -static pm_node_t * +static const pm_node_t * pm_node_stack_pop(pm_node_stack_node_t **stack) { pm_node_stack_node_t *current = *stack; - pm_node_t *visit = current->visit; + const pm_node_t *visit = current->visit; *stack = current->prev; free(current); @@ -78,7 +95,7 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) { } VALUE -pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE source) { +pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source) { ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); for (uint32_t index = 0; index < parser->constant_pool.size; index++) { @@ -108,7 +125,7 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE so continue; } - pm_node_t *node = node_stack->visit; + const pm_node_t *node = node_stack->visit; node_stack->visited = true; switch (PM_NODE_TYPE(node)) { @@ -136,7 +153,7 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE so } #line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" } else { - pm_node_t *node = pm_node_stack_pop(&node_stack); + const pm_node_t *node = pm_node_stack_pop(&node_stack); switch (PM_NODE_TYPE(node)) { <%- nodes.each do |node| -%> @@ -193,6 +210,9 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding, VALUE so <%- when Prism::FlagsField -%> #line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" argv[<%= index %>] = ULONG2NUM(node->flags & ~PM_NODE_FLAG_COMMON_MASK); + <%- when Prism::IntegerField -%> +#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" + argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb index 13b923b029262c..e75fdd51abf25d 100644 --- a/prism/templates/include/prism/ast.h.erb +++ b/prism/templates/include/prism/ast.h.erb @@ -183,6 +183,7 @@ typedef struct pm_<%= node.human %> { when Prism::LocationField, Prism::OptionalLocationField then "pm_location_t #{field.name}" when Prism::UInt8Field then "uint8_t #{field.name}" when Prism::UInt32Field then "uint32_t #{field.name}" + when Prism::IntegerField then "pm_number_t #{field.name}" else raise field.class.name end %>; diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb index fc3dd4b2234009..7689bc913f5cf9 100644 --- a/prism/templates/lib/prism/dot_visitor.rb.erb +++ b/prism/templates/lib/prism/dot_visitor.rb.erb @@ -133,7 +133,7 @@ module Prism else table.field("<%= field.name %>", "[]") end - <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField -%> + <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField, Prism::IntegerField -%> table.field("<%= field.name %>", node.<%= field.name %>.inspect) <%- when Prism::LocationField -%> table.field("<%= field.name %>", location_inspect(node.<%= field.name %>)) diff --git a/prism/templates/lib/prism/dsl.rb.erb b/prism/templates/lib/prism/dsl.rb.erb index d21cf5302299c1..7c55fb10bcd1fd 100644 --- a/prism/templates/lib/prism/dsl.rb.erb +++ b/prism/templates/lib/prism/dsl.rb.erb @@ -8,6 +8,7 @@ module Prism # [ # Prism::IntegerNode.new( # Prism::IntegerBaseFlags::DECIMAL, + # 1, # Prism::Location.new(source, 1, 1), # source # ) @@ -22,7 +23,7 @@ module Prism # source = Prism::Source.new("[1]") # # ArrayNode( - # IntegerNode(Prism::IntegerBaseFlags::DECIMAL, Location(source, 1, 1)), source), + # IntegerNode(Prism::IntegerBaseFlags::DECIMAL, 1, Location(source, 1, 1)), source), # Location(source, 0, 1), # Location(source, 2, 1), # source diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 2eb385c09aeb3f..df8f16a1e8ffd9 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -281,7 +281,7 @@ module Prism inspector << "<%= pointer %><%= field.name %>:\n" inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix) end - <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field -%> + <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field, Prism::IntegerField -%> inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n" <%- when Prism::OptionalConstantField -%> if (<%= field.name %> = self.<%= field.name %>).nil? diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 5193dfdecae970..0214913c19b0fe 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -172,6 +172,17 @@ module Prism (n >> 1) ^ (-(n & 1)) end + def load_integer + negative = io.getbyte != 0 + length = load_varuint + + value = 0 + length.times { |index| value |= (load_varuint << (index * 32)) } + + value = -value if negative + value + end + def load_serialized_length io.read(4).unpack1("L") end @@ -288,6 +299,7 @@ module Prism when Prism::OptionalLocationField then "load_optional_location" when Prism::UInt8Field then "io.getbyte" when Prism::UInt32Field, Prism::FlagsField then "load_varuint" + when Prism::IntegerField then "load_integer" else raise end } + ["location"]).join(", ") -%>) @@ -323,6 +335,7 @@ module Prism when Prism::OptionalLocationField then "load_optional_location" when Prism::UInt8Field then "io.getbyte" when Prism::UInt32Field, Prism::FlagsField then "load_varuint" + when Prism::IntegerField then "load_integer" else raise end } + ["location"]).join(", ") -%>) diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index 095a2b171ee7a0..bc5eca43a0e194 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -74,6 +74,8 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { pm_node_list_free(parser, &cast-><%= field.name %>); <%- when Prism::ConstantListField -%> pm_constant_id_list_free(&cast-><%= field.name %>); + <%- when Prism::IntegerField -%> + pm_number_free(&cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> @@ -103,14 +105,6 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { case <%= node.type %>: { pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; memsize->memsize += sizeof(*cast); - <%- if node.fields.any? { |f| f.is_a?(Prism::NodeListField) } -%> - // Node lists will add in their own sizes below. - memsize->memsize -= sizeof(pm_node_list_t) * <%= node.fields.count { |f| f.is_a?(Prism::NodeListField) } %>; - <%- end -%> - <%- if node.fields.any? { |f| f.is_a?(Prism::ConstantListField) } -%> - // Constant id lists will add in their own sizes below. - memsize->memsize -= sizeof(pm_constant_id_list_t) * <%= node.fields.count { |f| f.is_a?(Prism::ConstantListField) } %>; - <%- end -%> <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::LocationField, Prism::OptionalLocationField -%> @@ -121,11 +115,13 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { pm_node_memsize_node((pm_node_t *)cast-><%= field.name %>, memsize); } <%- when Prism::StringField -%> - memsize->memsize += pm_string_memsize(&cast-><%= field.name %>); + memsize->memsize += (pm_string_memsize(&cast-><%= field.name %>) - sizeof(pm_string_t)); <%- when Prism::NodeListField -%> - memsize->memsize += pm_node_list_memsize(&cast-><%= field.name %>, memsize); + memsize->memsize += (pm_node_list_memsize(&cast-><%= field.name %>, memsize) - sizeof(pm_node_list_t)); <%- when Prism::ConstantListField -%> - memsize->memsize += pm_constant_id_list_memsize(&cast-><%= field.name %>); + memsize->memsize += (pm_constant_id_list_memsize(&cast-><%= field.name %>) - sizeof(pm_constant_id_list_t)); + <%- when Prism::IntegerField -%> + memsize->memsize += (pm_number_memsize(&cast-><%= field.name %>) - sizeof(pm_number_t)); <%- else -%> <%- raise -%> <%- end -%> @@ -257,6 +253,29 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no } <%- end -%> pm_buffer_append_byte(buffer, ']'); + <%- when Prism::IntegerField -%> + { + const pm_number_t *number = &cast-><%= field.name %>; + if (number->length == 0) { + if (number->negative) pm_buffer_append_byte(buffer, '-'); + pm_buffer_append_string(buffer, "%" PRIu32, number->head.value); + } else if (number->length == 1) { + if (number->negative) pm_buffer_append_byte(buffer, '-'); + pm_buffer_append_format(buffer, "%" PRIu64, ((uint64_t) number->head.value) | (((uint64_t) number->head.next->value) << 32)); + } else { + pm_buffer_append_byte(buffer, '{'); + pm_buffer_append_format(buffer, "\"negative\": %s", number->negative ? "true" : "false"); + pm_buffer_append_string(buffer, ",\"values\":[", 11); + + const pm_number_node_t *node = &number->head; + while (node != NULL) { + pm_buffer_append_format(buffer, "%" PRIu32, node->value); + node = node->next; + if (node != NULL) pm_buffer_append_byte(buffer, ','); + } + pm_buffer_append_string(buffer, "]}", 2); + } + } <%- else -%> <%- raise %> <%- end -%> diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index c6dd5facef3ab8..799e8b91ef06d3 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -126,6 +126,36 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm <%- end -%> if (!found) pm_buffer_append_string(output_buffer, " nil", 4); pm_buffer_append_byte(output_buffer, '\n'); + <%- when Prism::IntegerField -%> + const pm_number_t *number = &cast-><%= field.name %>; + if (number->length == 0) { + pm_buffer_append_byte(output_buffer, ' '); + if (number->negative) pm_buffer_append_byte(output_buffer, '-'); + pm_buffer_append_string(output_buffer, "%" PRIu32 "\n", number->head.value); + } else if (number->length == 1) { + pm_buffer_append_byte(output_buffer, ' '); + if (number->negative) pm_buffer_append_byte(output_buffer, '-'); + pm_buffer_append_string(output_buffer, "%" PRIu64 "\n", ((uint64_t) number->head.value) | (((uint64_t) number->head.next->value) << 32)); + } else { + pm_buffer_append_byte(output_buffer, ' '); + + const pm_number_node_t *node = &number->head; + uint32_t index = 0; + + while (node != NULL) { + if (index != 0) pm_buffer_append_string(output_buffer, " | ", 3); + pm_buffer_append_format(output_buffer, "%" PRIu32, node->value); + + if (index != 0) { + pm_buffer_append_string(output_buffer, " << ", 4); + pm_buffer_append_format(output_buffer, "%" PRIu32, index * 32); + } + + node = node->next; + index++; + } + pm_buffer_append_string(output_buffer, "]\n", 2); + } <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb index 7c20e06ea945d0..cfa82d96f5e8f3 100644 --- a/prism/templates/src/serialize.c.erb +++ b/prism/templates/src/serialize.c.erb @@ -25,7 +25,7 @@ pm_serialize_location(const pm_parser_t *parser, const pm_location_t *location, } static void -pm_serialize_string(pm_parser_t *parser, pm_string_t *string, pm_buffer_t *buffer) { +pm_serialize_string(const pm_parser_t *parser, const pm_string_t *string, pm_buffer_t *buffer) { switch (string->type) { case PM_STRING_SHARED: { pm_buffer_append_byte(buffer, 1); @@ -49,6 +49,16 @@ pm_serialize_string(pm_parser_t *parser, pm_string_t *string, pm_buffer_t *buffe } } +static void +pm_serialize_integer(const pm_number_t *number, pm_buffer_t *buffer) { + pm_buffer_append_byte(buffer, number->negative ? 1 : 0); + pm_buffer_append_varuint(buffer, pm_sizet_to_u32(number->length + 1)); + + for (const pm_number_node_t *node = &number->head; node != NULL; node = node->next) { + pm_buffer_append_varuint(buffer, node->value); + } +} + static void pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_byte(buffer, (uint8_t) PM_NODE_TYPE(node)); @@ -115,6 +125,8 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_varuint(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>); <%- when Prism::FlagsField -%> pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); + <%- when Prism::IntegerField -%> + pm_serialize_integer(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 4576191701c76f..be769c2ddd5312 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -254,6 +254,22 @@ def kind end end + # This represents an arbitrarily-sized integer. When it gets to Ruby it will + # be an Integer. + class IntegerField < Field + def rbs_class + "Integer" + end + + def rbi_class + "Integer" + end + + def java_type + "VariableInteger" + end + end + # This class represents a node in the tree, configured by the config.yml file # in YAML format. It contains information about the name of the node and the # various child nodes it contains. @@ -315,6 +331,7 @@ def field_type_for(name) when "uint8" then UInt8Field when "uint32" then UInt32Field when "flags" then FlagsField + when "integer" then IntegerField else raise("Unknown field type: #{name.inspect}") end end diff --git a/prism/util/pm_number.c b/prism/util/pm_number.c index d2733330a64cc6..6f0a13ae8eb4d5 100644 --- a/prism/util/pm_number.c +++ b/prism/util/pm_number.c @@ -87,17 +87,11 @@ pm_number_parse_digit(const uint8_t character) { */ PRISM_EXPORTED_FUNCTION void pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end) { - switch (*start) { - case '-': - number->negative = true; - /* fallthrough */ - case '+': - start++; - break; - default: - break; - } + // Ignore unary +. Unary + is parsed differently and will not end up here. + // Instead, it will modify the parsed number later. + if (*start == '+') start++; + // Determine the multiplier from the base, and skip past any prefixes. uint32_t multiplier; switch (base) { case PM_NUMBER_BASE_BINARY: @@ -133,13 +127,29 @@ pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start break; } - for (pm_number_add(number, pm_number_parse_digit(*start++)); start < end; start++) { + // It's possible that we've consumed everything at this point if there is an + // invalid number. If this is the case, we'll just return 0. + if (start >= end) return; + + // Add the first digit to the number. + pm_number_add(number, pm_number_parse_digit(*start++)); + + // Add the subsequent digits to the number. + for (; start < end; start++) { if (*start == '_') continue; pm_number_multiply(number, multiplier); pm_number_add(number, pm_number_parse_digit(*start)); } } +/** + * Return the memory size of the number. + */ +size_t +pm_number_memsize(const pm_number_t *number) { + return sizeof(pm_number_t) + number->length * sizeof(pm_number_node_t); +} + /** * Recursively destroy the linked list of a number. */ diff --git a/prism/util/pm_number.h b/prism/util/pm_number.h index c2507cf1df42ca..04404ffa0dd642 100644 --- a/prism/util/pm_number.h +++ b/prism/util/pm_number.h @@ -84,6 +84,14 @@ typedef enum { */ PRISM_EXPORTED_FUNCTION void pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end); +/** + * Return the memory size of the number. + * + * @param number The number to get the memory size of. + * @return The size of the memory associated with the number. + */ +size_t pm_number_memsize(const pm_number_t *number); + /** * Free the internal memory of a number. This memory will only be allocated if * the number exceeds the size of a single node in the linked list. diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 6c9463ee924d1d..f4a19f83f282a4 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -966,8 +966,8 @@ def test_returning_to_optional_parameters_multiple_times ParametersNode( [RequiredParameterNode(0, :a)], [ - OptionalParameterNode(0, :b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)), - OptionalParameterNode(0, :d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)) + OptionalParameterNode(0, :b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1)), + OptionalParameterNode(0, :d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 2)) ], nil, [RequiredParameterNode(0, :c), RequiredParameterNode(0, :e)], @@ -1024,7 +1024,7 @@ def test_setter_method_cannot_be_defined_in_an_endless_method_definition Location(), nil, nil, - StatementsNode([IntegerNode(IntegerBaseFlags::DECIMAL)]), + StatementsNode([IntegerNode(IntegerBaseFlags::DECIMAL, 42)]), [], Location(), nil, @@ -1214,7 +1214,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([], [OptionalParameterNode(0, :a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL))], RestParameterNode(0, :c, Location(), Location()), [RequiredParameterNode(0, :b)], [], nil, nil), + ParametersNode([], [OptionalParameterNode(0, :a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1))], RestParameterNode(0, :c, Location(), Location()), [RequiredParameterNode(0, :b)], [], nil, nil), nil, [:a, :b, :c], Location(), From 3b3def5db7c27e985c12d8d2cf0f77ef3eb63744 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 22 Feb 2024 10:55:52 -0500 Subject: [PATCH 011/147] [ruby/prism] Regenerate snapshots using integer values --- lib/prism/prism.gemspec | 2 + prism/extension.c | 20 +- prism/prism.c | 14 +- prism/prism.h | 2 +- prism/templates/ext/prism/api_node.c.erb | 8 +- prism/templates/include/prism/ast.h.erb | 3 +- prism/templates/src/node.c.erb | 22 +- prism/templates/src/prettyprint.c.erb | 16 +- prism/templates/src/serialize.c.erb | 8 +- prism/templates/template.rb | 2 +- prism/util/pm_integer.c | 176 ++++++++++++++++ prism/util/pm_integer.h | 104 +++++++++ prism/util/pm_number.c | 174 --------------- prism/util/pm_number.h | 103 --------- test/prism/integer_parse_test.rb | 37 ++++ test/prism/number_parse_test.rb | 36 ---- test/prism/snapshots/alias.txt | 3 +- test/prism/snapshots/arithmetic.txt | 9 +- test/prism/snapshots/arrays.txt | 120 +++++++---- test/prism/snapshots/blocks.txt | 18 +- test/prism/snapshots/break.txt | 57 +++-- test/prism/snapshots/case.txt | 45 ++-- test/prism/snapshots/classes.txt | 21 +- test/prism/snapshots/command_method_call.txt | 114 ++++++---- test/prism/snapshots/constants.txt | 15 +- test/prism/snapshots/dash_heredocs.txt | 6 +- test/prism/snapshots/defined.txt | 12 +- test/prism/snapshots/emoji_method_calls.txt | 3 +- test/prism/snapshots/endless_methods.txt | 12 +- .../endless_range_in_conditional.txt | 12 +- test/prism/snapshots/for.txt | 36 ++-- test/prism/snapshots/hashes.txt | 9 +- test/prism/snapshots/heredocs_nested.txt | 3 +- test/prism/snapshots/if.txt | 24 ++- test/prism/snapshots/integer_operations.txt | 198 ++++++++++++------ test/prism/snapshots/lambda.txt | 3 +- test/prism/snapshots/method_calls.txt | 51 +++-- test/prism/snapshots/methods.txt | 87 +++++--- test/prism/snapshots/modules.txt | 9 +- test/prism/snapshots/next.txt | 51 +++-- test/prism/snapshots/nils.txt | 6 +- test/prism/snapshots/numbers.txt | 87 +++++--- test/prism/snapshots/patterns.txt | 102 ++++++--- test/prism/snapshots/procs.txt | 9 +- .../snapshots/range_begin_open_exclusive.txt | 3 +- .../snapshots/range_begin_open_inclusive.txt | 3 +- .../snapshots/range_end_open_exclusive.txt | 3 +- .../snapshots/range_end_open_inclusive.txt | 3 +- test/prism/snapshots/ranges.txt | 123 +++++++---- test/prism/snapshots/regex.txt | 3 +- test/prism/snapshots/repeat_parameters.txt | 12 +- test/prism/snapshots/rescue.txt | 12 +- test/prism/snapshots/return.txt | 51 +++-- test/prism/snapshots/seattlerb/BEGIN.txt | 3 +- .../seattlerb/TestRubyParserShared.txt | 6 +- .../snapshots/seattlerb/aref_args_assocs.txt | 6 +- .../seattlerb/aref_args_lit_assocs.txt | 9 +- .../snapshots/seattlerb/args_kw_block.txt | 3 +- .../snapshots/seattlerb/array_line_breaks.txt | 3 +- .../prism/snapshots/seattlerb/assoc_label.txt | 3 +- .../seattlerb/attr_asgn_colon_id.txt | 3 +- .../seattlerb/attrasgn_array_arg.txt | 9 +- .../seattlerb/attrasgn_array_lhs.txt | 12 +- .../attrasgn_primary_dot_constant.txt | 3 +- test/prism/snapshots/seattlerb/bang_eq.txt | 6 +- test/prism/snapshots/seattlerb/bdot2.txt | 3 +- test/prism/snapshots/seattlerb/bdot3.txt | 3 +- .../begin_rescue_else_ensure_bodies.txt | 12 +- .../seattlerb/block_arg_opt_arg_block.txt | 3 +- .../seattlerb/block_arg_opt_splat.txt | 3 +- .../block_arg_opt_splat_arg_block_omfg.txt | 3 +- .../seattlerb/block_arg_optional.txt | 3 +- .../snapshots/seattlerb/block_args_opt1.txt | 3 +- .../snapshots/seattlerb/block_args_opt2.txt | 6 +- .../snapshots/seattlerb/block_args_opt2_2.txt | 6 +- .../snapshots/seattlerb/block_args_opt3.txt | 6 +- test/prism/snapshots/seattlerb/block_kw.txt | 3 +- .../snapshots/seattlerb/block_opt_arg.txt | 3 +- .../snapshots/seattlerb/block_opt_splat.txt | 3 +- .../block_opt_splat_arg_block_omfg.txt | 3 +- test/prism/snapshots/seattlerb/bug202.txt | 6 +- .../seattlerb/bug_call_arglist_parens.txt | 18 +- test/prism/snapshots/seattlerb/call_and.txt | 6 +- .../snapshots/seattlerb/call_arg_assoc.txt | 9 +- .../seattlerb/call_arg_assoc_kwsplat.txt | 9 +- .../snapshots/seattlerb/call_arg_kwsplat.txt | 3 +- .../seattlerb/call_args_assoc_quoted.txt | 9 +- .../call_args_assoc_trailing_comma.txt | 9 +- .../snapshots/seattlerb/call_args_command.txt | 3 +- .../snapshots/seattlerb/call_array_arg.txt | 3 +- .../seattlerb/call_array_lit_inline_hash.txt | 3 +- test/prism/snapshots/seattlerb/call_assoc.txt | 6 +- .../snapshots/seattlerb/call_assoc_new.txt | 3 +- .../seattlerb/call_assoc_new_if_multiline.txt | 6 +- .../seattlerb/call_assoc_trailing_comma.txt | 6 +- .../seattlerb/call_bang_command_call.txt | 3 +- .../seattlerb/call_bang_squiggle.txt | 6 +- test/prism/snapshots/seattlerb/call_carat.txt | 6 +- .../snapshots/seattlerb/call_colon_parens.txt | 3 +- test/prism/snapshots/seattlerb/call_div.txt | 6 +- .../snapshots/seattlerb/call_dot_parens.txt | 3 +- test/prism/snapshots/seattlerb/call_eq3.txt | 6 +- test/prism/snapshots/seattlerb/call_gt.txt | 6 +- .../snapshots/seattlerb/call_kwsplat.txt | 3 +- test/prism/snapshots/seattlerb/call_lt.txt | 6 +- test/prism/snapshots/seattlerb/call_lte.txt | 6 +- test/prism/snapshots/seattlerb/call_not.txt | 3 +- test/prism/snapshots/seattlerb/call_pipe.txt | 6 +- .../prism/snapshots/seattlerb/call_rshift.txt | 6 +- .../seattlerb/call_self_brackets.txt | 3 +- .../snapshots/seattlerb/call_spaceship.txt | 6 +- .../call_stabby_do_end_with_block.txt | 6 +- .../call_stabby_with_braces_block.txt | 6 +- test/prism/snapshots/seattlerb/call_star.txt | 6 +- test/prism/snapshots/seattlerb/call_star2.txt | 6 +- .../seattlerb/call_trailing_comma.txt | 3 +- .../snapshots/seattlerb/call_unary_bang.txt | 3 +- test/prism/snapshots/seattlerb/case_in.txt | 18 +- test/prism/snapshots/seattlerb/case_in_67.txt | 3 +- .../case_in_hash_pat_paren_assign.txt | 3 +- .../snapshots/seattlerb/cond_unary_minus.txt | 3 +- .../seattlerb/const_2_op_asgn_or2.txt | 3 +- .../seattlerb/const_3_op_asgn_or.txt | 3 +- .../seattlerb/const_op_asgn_and1.txt | 3 +- .../seattlerb/const_op_asgn_and2.txt | 3 +- .../snapshots/seattlerb/const_op_asgn_or.txt | 3 +- .../snapshots/seattlerb/defined_eh_parens.txt | 3 +- .../seattlerb/defn_endless_command.txt | 3 +- .../seattlerb/defn_endless_command_rescue.txt | 6 +- .../snapshots/seattlerb/defn_kwarg_kwarg.txt | 6 +- .../seattlerb/defn_kwarg_kwsplat.txt | 3 +- .../seattlerb/defn_kwarg_kwsplat_anon.txt | 3 +- .../seattlerb/defn_kwarg_no_parens.txt | 3 +- .../snapshots/seattlerb/defn_kwarg_val.txt | 3 +- .../snapshots/seattlerb/defn_oneliner_eq2.txt | 3 +- .../seattlerb/defn_opt_splat_arg.txt | 3 +- .../seattlerb/defs_endless_command.txt | 3 +- .../seattlerb/defs_endless_command_rescue.txt | 6 +- test/prism/snapshots/seattlerb/defs_kwarg.txt | 3 +- .../snapshots/seattlerb/defs_oneliner_eq2.txt | 3 +- .../seattlerb/difficult1_line_numbers.txt | 42 ++-- .../seattlerb/difficult1_line_numbers2.txt | 6 +- .../prism/snapshots/seattlerb/difficult2_.txt | 9 +- .../seattlerb/difficult4__leading_dots2.txt | 6 +- .../snapshots/seattlerb/difficult6__7.txt | 3 +- .../snapshots/seattlerb/difficult6__8.txt | 3 +- test/prism/snapshots/seattlerb/do_bug.txt | 3 +- .../seattlerb/eq_begin_line_numbers.txt | 6 +- ...gin_why_wont_people_use_their_spacebar.txt | 3 +- test/prism/snapshots/seattlerb/f_kw.txt | 3 +- .../snapshots/seattlerb/heredoc_lineno.txt | 3 +- .../snapshots/seattlerb/heredoc_nested.txt | 3 +- .../seattlerb/heredoc_squiggly_interp.txt | 3 +- test/prism/snapshots/seattlerb/if_elsif.txt | 6 +- .../seattlerb/integer_with_if_modifier.txt | 3 +- .../interpolated_symbol_array_line_breaks.txt | 3 +- .../interpolated_word_array_line_breaks.txt | 3 +- .../snapshots/seattlerb/iter_args_10_1.txt | 3 +- .../snapshots/seattlerb/iter_args_10_2.txt | 3 +- .../snapshots/seattlerb/iter_args_11_1.txt | 3 +- .../snapshots/seattlerb/iter_args_11_2.txt | 3 +- .../prism/snapshots/seattlerb/iter_args_6.txt | 3 +- .../snapshots/seattlerb/iter_args_7_1.txt | 3 +- .../snapshots/seattlerb/iter_args_7_2.txt | 3 +- .../snapshots/seattlerb/iter_args_8_1.txt | 3 +- .../snapshots/seattlerb/iter_args_8_2.txt | 3 +- .../snapshots/seattlerb/iter_args_9_1.txt | 3 +- .../snapshots/seattlerb/iter_args_9_2.txt | 3 +- test/prism/snapshots/seattlerb/iter_kwarg.txt | 3 +- .../seattlerb/iter_kwarg_kwsplat.txt | 3 +- .../seattlerb/lasgn_arg_rescue_arg.txt | 6 +- .../lasgn_call_bracket_rescue_arg.txt | 6 +- .../lasgn_call_nobracket_rescue_arg.txt | 6 +- .../snapshots/seattlerb/lasgn_command.txt | 3 +- test/prism/snapshots/seattlerb/lasgn_env.txt | 3 +- .../snapshots/seattlerb/lasgn_ivar_env.txt | 3 +- .../seattlerb/lasgn_lasgn_command_call.txt | 3 +- .../snapshots/seattlerb/masgn_colon2.txt | 6 +- .../snapshots/seattlerb/masgn_colon3.txt | 6 +- .../seattlerb/masgn_command_call.txt | 3 +- .../snapshots/seattlerb/masgn_lhs_splat.txt | 9 +- test/prism/snapshots/seattlerb/masgn_star.txt | 3 +- .../method_call_assoc_trailing_comma.txt | 6 +- .../seattlerb/method_call_trailing_comma.txt | 3 +- .../prism/snapshots/seattlerb/mlhs_rescue.txt | 3 +- ..._interpolated_symbol_array_line_breaks.txt | 3 +- ...on_interpolated_word_array_line_breaks.txt | 3 +- .../seattlerb/op_asgn_command_call.txt | 3 +- .../op_asgn_dot_ident_command_call.txt | 3 +- .../seattlerb/op_asgn_index_command_call.txt | 6 +- .../op_asgn_primary_colon_identifier1.txt | 3 +- .../op_asgn_val_dot_ident_command_call.txt | 3 +- .../snapshots/seattlerb/parse_line_block.txt | 3 +- .../seattlerb/parse_line_defn_complex.txt | 3 +- .../snapshots/seattlerb/parse_line_dot2.txt | 6 +- .../seattlerb/parse_line_dot2_open.txt | 3 +- .../snapshots/seattlerb/parse_line_dot3.txt | 6 +- .../seattlerb/parse_line_dot3_open.txt | 3 +- .../seattlerb/parse_line_hash_lit.txt | 3 +- .../seattlerb/parse_line_multiline_str.txt | 3 +- .../parse_line_multiline_str_literal_n.txt | 3 +- .../snapshots/seattlerb/parse_line_return.txt | 3 +- .../parse_opt_call_args_assocs_comma.txt | 9 +- .../parse_opt_call_args_lit_comma.txt | 6 +- .../snapshots/seattlerb/parse_pattern_019.txt | 9 +- .../snapshots/seattlerb/parse_pattern_051.txt | 15 +- .../snapshots/seattlerb/parse_pattern_058.txt | 3 +- .../seattlerb/parse_pattern_058_2.txt | 3 +- .../snapshots/seattlerb/parse_pattern_069.txt | 6 +- .../snapshots/seattlerb/parse_pattern_076.txt | 6 +- .../snapshots/seattlerb/qsymbols_interp.txt | 6 +- .../seattlerb/return_call_assocs.txt | 27 ++- test/prism/snapshots/seattlerb/rhs_asgn.txt | 3 +- .../snapshots/seattlerb/ruby21_numbers.txt | 9 +- .../snapshots/seattlerb/safe_attrasgn.txt | 3 +- .../seattlerb/safe_attrasgn_constant.txt | 3 +- .../seattlerb/safe_call_operator.txt | 3 +- test/prism/snapshots/seattlerb/safe_calls.txt | 3 +- .../snapshots/seattlerb/safe_op_asgn.txt | 3 +- .../stabby_arg_opt_splat_arg_block_omfg.txt | 3 +- ...bby_block_iter_call_no_target_with_arg.txt | 3 +- .../snapshots/seattlerb/stabby_block_kw.txt | 3 +- .../str_newline_hash_line_number.txt | 3 +- .../seattlerb/str_pct_nested_nested.txt | 3 +- test/prism/snapshots/seattlerb/super_arg.txt | 3 +- test/prism/snapshots/seattlerb/thingy.txt | 6 +- test/prism/snapshots/seattlerb/utf8_bom.txt | 3 +- .../snapshots/seattlerb/words_interp.txt | 3 +- test/prism/snapshots/seattlerb/yield_arg.txt | 3 +- .../snapshots/seattlerb/yield_call_assocs.txt | 27 ++- test/prism/snapshots/super.txt | 30 ++- test/prism/snapshots/symbols.txt | 21 +- test/prism/snapshots/ternary_operator.txt | 6 +- test/prism/snapshots/tilde_heredocs.txt | 21 +- test/prism/snapshots/undef.txt | 3 +- test/prism/snapshots/unless.txt | 12 +- .../unparser/corpus/literal/assignment.txt | 120 +++++++---- .../unparser/corpus/literal/block.txt | 3 +- .../unparser/corpus/literal/case.txt | 3 +- .../unparser/corpus/literal/control.txt | 33 ++- .../snapshots/unparser/corpus/literal/def.txt | 3 +- .../unparser/corpus/literal/defined.txt | 6 +- .../unparser/corpus/literal/defs.txt | 3 +- .../unparser/corpus/literal/dstr.txt | 3 +- .../unparser/corpus/literal/flipflop.txt | 12 +- .../snapshots/unparser/corpus/literal/if.txt | 24 ++- .../unparser/corpus/literal/literal.txt | 93 +++++--- .../unparser/corpus/literal/opasgn.txt | 60 ++++-- .../unparser/corpus/literal/pattern.txt | 51 +++-- .../unparser/corpus/literal/range.txt | 18 +- .../unparser/corpus/literal/send.txt | 27 ++- .../unparser/corpus/literal/since/27.txt | 3 +- .../unparser/corpus/literal/since/30.txt | 15 +- .../unparser/corpus/literal/unary.txt | 9 +- .../unparser/corpus/literal/while.txt | 6 +- .../unparser/corpus/semantic/literal.txt | 9 +- .../unparser/corpus/semantic/send.txt | 3 +- test/prism/snapshots/until.txt | 6 +- test/prism/snapshots/variables.txt | 87 +++++--- test/prism/snapshots/while.txt | 6 +- test/prism/snapshots/whitequark/and_asgn.txt | 12 +- test/prism/snapshots/whitequark/args.txt | 36 ++-- .../snapshots/whitequark/args_args_assocs.txt | 6 +- .../whitequark/args_args_assocs_comma.txt | 3 +- .../snapshots/whitequark/args_assocs.txt | 18 +- .../whitequark/args_assocs_comma.txt | 3 +- .../whitequark/args_assocs_legacy.txt | 18 +- .../snapshots/whitequark/array_assocs.txt | 15 +- .../snapshots/whitequark/array_plain.txt | 6 +- .../snapshots/whitequark/array_splat.txt | 9 +- test/prism/snapshots/whitequark/asgn_mrhs.txt | 3 +- .../snapshots/whitequark/begin_cmdarg.txt | 6 +- .../beginless_erange_after_newline.txt | 3 +- .../beginless_irange_after_newline.txt | 3 +- .../snapshots/whitequark/beginless_range.txt | 6 +- test/prism/snapshots/whitequark/blockargs.txt | 36 ++-- test/prism/snapshots/whitequark/bug_447.txt | 3 +- test/prism/snapshots/whitequark/bug_452.txt | 3 +- test/prism/snapshots/whitequark/bug_466.txt | 6 +- test/prism/snapshots/whitequark/bug_481.txt | 3 +- .../whitequark/bug_interp_single.txt | 6 +- .../snapshots/whitequark/casgn_scoped.txt | 3 +- .../snapshots/whitequark/casgn_toplevel.txt | 3 +- .../snapshots/whitequark/casgn_unscoped.txt | 3 +- test/prism/snapshots/whitequark/complex.txt | 6 +- .../snapshots/whitequark/const_op_asgn.txt | 15 +- test/prism/snapshots/whitequark/cvasgn.txt | 3 +- .../snapshots/whitequark/endless_method.txt | 12 +- .../endless_method_with_rescue_mod.txt | 12 +- .../endless_method_without_args.txt | 12 +- .../whitequark/forward_arg_with_open_args.txt | 9 +- test/prism/snapshots/whitequark/gvasgn.txt | 3 +- .../snapshots/whitequark/hash_hashrocket.txt | 12 +- .../snapshots/whitequark/hash_kwsplat.txt | 3 +- .../prism/snapshots/whitequark/hash_label.txt | 3 +- .../snapshots/whitequark/hash_label_end.txt | 9 +- test/prism/snapshots/whitequark/if_elsif.txt | 6 +- test/prism/snapshots/whitequark/int.txt | 9 +- test/prism/snapshots/whitequark/ivasgn.txt | 3 +- test/prism/snapshots/whitequark/kwoptarg.txt | 3 +- test/prism/snapshots/whitequark/lvasgn.txt | 3 +- test/prism/snapshots/whitequark/masgn.txt | 18 +- .../prism/snapshots/whitequark/masgn_attr.txt | 6 +- .../whitequark/multiple_pattern_matches.txt | 12 +- .../whitequark/newline_in_hash_argument.txt | 12 +- .../whitequark/non_lvar_injecting_match.txt | 3 +- test/prism/snapshots/whitequark/op_asgn.txt | 9 +- .../snapshots/whitequark/op_asgn_index.txt | 9 +- .../whitequark/op_asgn_index_cmd.txt | 6 +- test/prism/snapshots/whitequark/optarg.txt | 9 +- test/prism/snapshots/whitequark/or_asgn.txt | 12 +- .../pattern_matching__FILE__LINE_literals.txt | 3 +- .../pattern_matching_blank_else.txt | 9 +- .../whitequark/pattern_matching_else.txt | 12 +- .../pattern_matching_single_line.txt | 6 +- ...e_line_allowed_omission_of_parentheses.txt | 18 +- test/prism/snapshots/whitequark/postexe.txt | 3 +- test/prism/snapshots/whitequark/preexe.txt | 3 +- .../snapshots/whitequark/range_exclusive.txt | 6 +- .../snapshots/whitequark/range_inclusive.txt | 6 +- test/prism/snapshots/whitequark/rational.txt | 3 +- .../snapshots/whitequark/rescue_mod_masgn.txt | 6 +- .../snapshots/whitequark/ruby_bug_10279.txt | 3 +- .../snapshots/whitequark/ruby_bug_10653.txt | 6 +- .../snapshots/whitequark/ruby_bug_11380.txt | 3 +- .../snapshots/whitequark/ruby_bug_11873_a.txt | 12 +- .../snapshots/whitequark/ruby_bug_12073.txt | 6 +- .../snapshots/whitequark/ruby_bug_12402.txt | 6 +- .../snapshots/whitequark/ruby_bug_9669.txt | 3 +- .../snapshots/whitequark/send_attr_asgn.txt | 12 +- .../whitequark/send_attr_asgn_conditional.txt | 3 +- .../snapshots/whitequark/send_binary_op.txt | 63 ++++-- .../whitequark/send_block_chain_cmd.txt | 21 +- test/prism/snapshots/whitequark/send_call.txt | 6 +- .../prism/snapshots/whitequark/send_index.txt | 6 +- .../snapshots/whitequark/send_index_asgn.txt | 9 +- .../whitequark/send_index_asgn_legacy.txt | 9 +- .../whitequark/send_index_legacy.txt | 6 +- .../whitequark/send_lambda_args_noparen.txt | 3 +- .../whitequark/send_op_asgn_conditional.txt | 3 +- test/prism/snapshots/whitequark/send_self.txt | 3 +- .../snapshots/whitequark/send_self_block.txt | 3 +- .../snapshots/whitequark/space_args_arg.txt | 3 +- .../whitequark/space_args_arg_block.txt | 9 +- .../whitequark/space_args_arg_call.txt | 3 +- .../whitequark/space_args_arg_newline.txt | 3 +- test/prism/snapshots/whitequark/ternary.txt | 6 +- .../whitequark/ternary_ambiguous_symbol.txt | 3 +- .../whitequark/trailing_forward_arg.txt | 3 +- .../whitequark/unary_num_pow_precedence.txt | 12 +- test/prism/snapshots/whitequark/undef.txt | 3 +- .../snapshots/whitequark/var_and_asgn.txt | 3 +- .../snapshots/whitequark/var_op_asgn.txt | 12 +- .../snapshots/whitequark/var_or_asgn.txt | 3 +- .../prism/snapshots/whitequark/when_splat.txt | 3 +- test/prism/snapshots/yield.txt | 12 +- 356 files changed, 2823 insertions(+), 1588 deletions(-) create mode 100644 prism/util/pm_integer.c create mode 100644 prism/util/pm_integer.h delete mode 100644 prism/util/pm_number.c delete mode 100644 prism/util/pm_number.h create mode 100644 test/prism/integer_parse_test.rb delete mode 100644 test/prism/number_parse_test.rb diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 902a1f235f7425..5017d671aec976 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -57,6 +57,7 @@ Gem::Specification.new do |spec| "include/prism/util/pm_buffer.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", + "include/prism/util/pm_integer.h", "include/prism/util/pm_list.h", "include/prism/util/pm_memchr.h", "include/prism/util/pm_newline_list.h", @@ -107,6 +108,7 @@ Gem::Specification.new do |spec| "src/util/pm_buffer.c", "src/util/pm_char.c", "src/util/pm_constant_pool.c", + "src/util/pm_integer.c", "src/util/pm_list.c", "src/util/pm_memchr.c", "src/util/pm_newline_list.c", diff --git a/prism/extension.c b/prism/extension.c index 4af28bdb9672b4..fd2281fd79747b 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -951,28 +951,28 @@ named_captures(VALUE self, VALUE source) { /** * call-seq: - * Debug::number_parse(source) -> Integer + * Debug::integer_parse(source) -> Integer * - * Parses the given source string and returns the number it represents. + * Parses the given source string and returns the integer it represents. */ static VALUE -number_parse(VALUE self, VALUE source) { +integer_parse(VALUE self, VALUE source) { const uint8_t *start = (const uint8_t *) RSTRING_PTR(source); size_t length = RSTRING_LEN(source); - pm_number_t number = { 0 }; - pm_number_parse(&number, PM_NUMBER_BASE_UNKNOWN, start, start + length); + pm_integer_t integer = { 0 }; + pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length); - VALUE result = UINT2NUM(number.head.value); + VALUE result = UINT2NUM(integer.head.value); size_t shift = 0; - for (pm_number_node_t *node = number.head.next; node != NULL; node = node->next) { + for (pm_integer_word_t *node = integer.head.next; node != NULL; node = node->next) { VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); result = rb_funcall(receiver, rb_intern("|"), 1, result); } - if (number.negative) result = rb_funcall(result, rb_intern("-@"), 0); - pm_number_free(&number); + if (integer.negative) result = rb_funcall(result, rb_intern("-@"), 0); + pm_integer_free(&integer); return result; } @@ -1176,7 +1176,7 @@ Init_prism(void) { // internal tasks. We expose these to make them easier to test. VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug"); rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1); - rb_define_singleton_method(rb_cPrismDebug, "number_parse", number_parse, 1); + rb_define_singleton_method(rb_cPrismDebug, "integer_parse", integer_parse, 1); rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1); rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); diff --git a/prism/prism.c b/prism/prism.c index a1b2bf74e28816..e14911167ab1f9 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3812,16 +3812,16 @@ pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token .value = { 0 } }; - pm_number_base_t number_base; + pm_integer_base_t integer_base = PM_INTEGER_BASE_DECIMAL; switch (base) { - case PM_INTEGER_BASE_FLAGS_BINARY: number_base = PM_NUMBER_BASE_BINARY; break; - case PM_INTEGER_BASE_FLAGS_OCTAL: number_base = PM_NUMBER_BASE_OCTAL; break; - case PM_INTEGER_BASE_FLAGS_DECIMAL: number_base = PM_NUMBER_BASE_DECIMAL; break; - case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: number_base = PM_NUMBER_BASE_HEXADECIMAL; break; - default: assert(false && "unreachable"); + case PM_INTEGER_BASE_FLAGS_BINARY: integer_base = PM_INTEGER_BASE_BINARY; break; + case PM_INTEGER_BASE_FLAGS_OCTAL: integer_base = PM_INTEGER_BASE_OCTAL; break; + case PM_INTEGER_BASE_FLAGS_DECIMAL: break; + case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: integer_base = PM_INTEGER_BASE_HEXADECIMAL; break; + default: assert(false && "unreachable"); break; } - pm_number_parse(&node->value, number_base, token->start, token->end); + pm_integer_parse(&node->value, integer_base, token->start, token->end); return node; } diff --git a/prism/prism.h b/prism/prism.h index 88eb128769225d..f26ca0c7848281 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -9,8 +9,8 @@ #include "prism/defines.h" #include "prism/util/pm_buffer.h" #include "prism/util/pm_char.h" +#include "prism/util/pm_integer.h" #include "prism/util/pm_memchr.h" -#include "prism/util/pm_number.h" #include "prism/util/pm_strncasecmp.h" #include "prism/util/pm_strpbrk.h" #include "prism/ast.h" diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb index 38288918d8bcce..c669a4aac9e7fb 100644 --- a/prism/templates/ext/prism/api_node.c.erb +++ b/prism/templates/ext/prism/api_node.c.erb @@ -38,16 +38,16 @@ pm_string_new(const pm_string_t *string, rb_encoding *encoding) { } static VALUE -pm_integer_new(const pm_number_t *number) { - VALUE result = UINT2NUM(number->head.value); +pm_integer_new(const pm_integer_t *integer) { + VALUE result = UINT2NUM(integer->head.value); size_t shift = 0; - for (const pm_number_node_t *node = number->head.next; node != NULL; node = node->next) { + for (const pm_integer_word_t *node = integer->head.next; node != NULL; node = node->next) { VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); result = rb_funcall(receiver, rb_intern("|"), 1, result); } - if (number->negative) { + if (integer->negative) { result = rb_funcall(result, rb_intern("-@"), 0); } diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb index e75fdd51abf25d..d1c94fe541fa51 100644 --- a/prism/templates/include/prism/ast.h.erb +++ b/prism/templates/include/prism/ast.h.erb @@ -8,6 +8,7 @@ #include "prism/defines.h" #include "prism/util/pm_constant_pool.h" +#include "prism/util/pm_integer.h" #include "prism/util/pm_string.h" #include @@ -183,7 +184,7 @@ typedef struct pm_<%= node.human %> { when Prism::LocationField, Prism::OptionalLocationField then "pm_location_t #{field.name}" when Prism::UInt8Field then "uint8_t #{field.name}" when Prism::UInt32Field then "uint32_t #{field.name}" - when Prism::IntegerField then "pm_number_t #{field.name}" + when Prism::IntegerField then "pm_integer_t #{field.name}" else raise field.class.name end %>; diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index bc5eca43a0e194..082d1a36980032 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -75,7 +75,7 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { <%- when Prism::ConstantListField -%> pm_constant_id_list_free(&cast-><%= field.name %>); <%- when Prism::IntegerField -%> - pm_number_free(&cast-><%= field.name %>); + pm_integer_free(&cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> @@ -121,7 +121,7 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { <%- when Prism::ConstantListField -%> memsize->memsize += (pm_constant_id_list_memsize(&cast-><%= field.name %>) - sizeof(pm_constant_id_list_t)); <%- when Prism::IntegerField -%> - memsize->memsize += (pm_number_memsize(&cast-><%= field.name %>) - sizeof(pm_number_t)); + memsize->memsize += (pm_integer_memsize(&cast-><%= field.name %>) - sizeof(pm_integer_t)); <%- else -%> <%- raise -%> <%- end -%> @@ -255,19 +255,19 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no pm_buffer_append_byte(buffer, ']'); <%- when Prism::IntegerField -%> { - const pm_number_t *number = &cast-><%= field.name %>; - if (number->length == 0) { - if (number->negative) pm_buffer_append_byte(buffer, '-'); - pm_buffer_append_string(buffer, "%" PRIu32, number->head.value); - } else if (number->length == 1) { - if (number->negative) pm_buffer_append_byte(buffer, '-'); - pm_buffer_append_format(buffer, "%" PRIu64, ((uint64_t) number->head.value) | (((uint64_t) number->head.next->value) << 32)); + const pm_integer_t *integer = &cast-><%= field.name %>; + if (integer->length == 0) { + if (integer->negative) pm_buffer_append_byte(buffer, '-'); + pm_buffer_append_string(buffer, "%" PRIu32, integer->head.value); + } else if (integer->length == 1) { + if (integer->negative) pm_buffer_append_byte(buffer, '-'); + pm_buffer_append_format(buffer, "%" PRIu64, ((uint64_t) integer->head.value) | (((uint64_t) integer->head.next->value) << 32)); } else { pm_buffer_append_byte(buffer, '{'); - pm_buffer_append_format(buffer, "\"negative\": %s", number->negative ? "true" : "false"); + pm_buffer_append_format(buffer, "\"negative\": %s", integer->negative ? "true" : "false"); pm_buffer_append_string(buffer, ",\"values\":[", 11); - const pm_number_node_t *node = &number->head; + const pm_integer_word_t *node = &integer->head; while (node != NULL) { pm_buffer_append_format(buffer, "%" PRIu32, node->value); node = node->next; diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index 799e8b91ef06d3..dafe3671f12f19 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -127,19 +127,19 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm if (!found) pm_buffer_append_string(output_buffer, " nil", 4); pm_buffer_append_byte(output_buffer, '\n'); <%- when Prism::IntegerField -%> - const pm_number_t *number = &cast-><%= field.name %>; - if (number->length == 0) { + const pm_integer_t *integer = &cast-><%= field.name %>; + if (integer->length == 0) { pm_buffer_append_byte(output_buffer, ' '); - if (number->negative) pm_buffer_append_byte(output_buffer, '-'); - pm_buffer_append_string(output_buffer, "%" PRIu32 "\n", number->head.value); - } else if (number->length == 1) { + if (integer->negative) pm_buffer_append_byte(output_buffer, '-'); + pm_buffer_append_format(output_buffer, "%" PRIu32 "\n", integer->head.value); + } else if (integer->length == 1) { pm_buffer_append_byte(output_buffer, ' '); - if (number->negative) pm_buffer_append_byte(output_buffer, '-'); - pm_buffer_append_string(output_buffer, "%" PRIu64 "\n", ((uint64_t) number->head.value) | (((uint64_t) number->head.next->value) << 32)); + if (integer->negative) pm_buffer_append_byte(output_buffer, '-'); + pm_buffer_append_format(output_buffer, "%" PRIu64 "\n", ((uint64_t) integer->head.value) | (((uint64_t) integer->head.next->value) << 32)); } else { pm_buffer_append_byte(output_buffer, ' '); - const pm_number_node_t *node = &number->head; + const pm_integer_word_t *node = &integer->head; uint32_t index = 0; while (node != NULL) { diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb index cfa82d96f5e8f3..9e0fe1e4e877ec 100644 --- a/prism/templates/src/serialize.c.erb +++ b/prism/templates/src/serialize.c.erb @@ -50,11 +50,11 @@ pm_serialize_string(const pm_parser_t *parser, const pm_string_t *string, pm_buf } static void -pm_serialize_integer(const pm_number_t *number, pm_buffer_t *buffer) { - pm_buffer_append_byte(buffer, number->negative ? 1 : 0); - pm_buffer_append_varuint(buffer, pm_sizet_to_u32(number->length + 1)); +pm_serialize_integer(const pm_integer_t *integer, pm_buffer_t *buffer) { + pm_buffer_append_byte(buffer, integer->negative ? 1 : 0); + pm_buffer_append_varuint(buffer, pm_sizet_to_u32(integer->length + 1)); - for (const pm_number_node_t *node = &number->head; node != NULL; node = node->next) { + for (const pm_integer_word_t *node = &integer->head; node != NULL; node = node->next) { pm_buffer_append_varuint(buffer, node->value); } } diff --git a/prism/templates/template.rb b/prism/templates/template.rb index be769c2ddd5312..8e20042bb82877 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -266,7 +266,7 @@ def rbi_class end def java_type - "VariableInteger" + "Object" end end diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c new file mode 100644 index 00000000000000..f08078356a531a --- /dev/null +++ b/prism/util/pm_integer.c @@ -0,0 +1,176 @@ +#include "prism/util/pm_integer.h" + +/** + * Create a new node for an integer in the linked list. + */ +static pm_integer_word_t * +pm_integer_node_create(pm_integer_t *integer, uint32_t value) { + integer->length++; + + pm_integer_word_t *node = malloc(sizeof(pm_integer_word_t)); + if (node == NULL) return NULL; + + *node = (pm_integer_word_t) { .next = NULL, .value = value }; + return node; +} + +/** + * Add a 32-bit integer to an integer. + */ +static void +pm_integer_add(pm_integer_t *integer, uint32_t addend) { + uint32_t carry = addend; + pm_integer_word_t *current = &integer->head; + + while (carry > 0) { + uint64_t result = (uint64_t) current->value + carry; + carry = (uint32_t) (result >> 32); + current->value = (uint32_t) result; + + if (carry > 0) { + if (current->next == NULL) { + current->next = pm_integer_node_create(integer, carry); + break; + } + + current = current->next; + } + } +} + +/** + * Multiple an integer by a 32-bit integer. In practice, the multiplier is the + * base of the integer, so this is 2, 8, 10, or 16. + */ +static void +pm_integer_multiply(pm_integer_t *integer, uint32_t multiplier) { + uint32_t carry = 0; + + for (pm_integer_word_t *current = &integer->head; current != NULL; current = current->next) { + uint64_t result = (uint64_t) current->value * multiplier + carry; + carry = (uint32_t) (result >> 32); + current->value = (uint32_t) result; + + if (carry > 0 && current->next == NULL) { + current->next = pm_integer_node_create(integer, carry); + break; + } + } +} + +/** + * Return the value of a digit in a uint32_t. + */ +static uint32_t +pm_integer_parse_digit(const uint8_t character) { + switch (character) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: assert(false && "unreachable"); return 0; + } +} + +/** + * Parse an integer from a string. This assumes that the format of the integer + * has already been validated, as internal validation checks are not performed + * here. + */ +PRISM_EXPORTED_FUNCTION void +pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end) { + // Ignore unary +. Unary + is parsed differently and will not end up here. + // Instead, it will modify the parsed integer later. + if (*start == '+') start++; + + // Determine the multiplier from the base, and skip past any prefixes. + uint32_t multiplier = 10; + switch (base) { + case PM_INTEGER_BASE_BINARY: + start += 2; // 0b + multiplier = 2; + break; + case PM_INTEGER_BASE_OCTAL: + start++; // 0 + if (*start == '_' || *start == 'o' || *start == 'O') start++; // o + multiplier = 8; + break; + case PM_INTEGER_BASE_DECIMAL: + if (*start == '0' && (end - start) > 1) start += 2; // 0d + break; + case PM_INTEGER_BASE_HEXADECIMAL: + start += 2; // 0x + multiplier = 16; + break; + case PM_INTEGER_BASE_UNKNOWN: + if (*start == '0' && (end - start) > 1) { + switch (start[1]) { + case '_': start += 2; multiplier = 8; break; + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': start++; multiplier = 8; break; + case 'b': case 'B': start += 2; multiplier = 2; break; + case 'o': case 'O': start += 2; multiplier = 8; break; + case 'd': case 'D': start += 2; break; + case 'x': case 'X': start += 2; multiplier = 16; break; + default: assert(false && "unreachable"); break; + } + } + break; + } + + // It's possible that we've consumed everything at this point if there is an + // invalid integer. If this is the case, we'll just return 0. + if (start >= end) return; + + // Add the first digit to the integer. + pm_integer_add(integer, pm_integer_parse_digit(*start++)); + + // Add the subsequent digits to the integer. + for (; start < end; start++) { + if (*start == '_') continue; + pm_integer_multiply(integer, multiplier); + pm_integer_add(integer, pm_integer_parse_digit(*start)); + } +} + +/** + * Return the memory size of the integer. + */ +size_t +pm_integer_memsize(const pm_integer_t *integer) { + return sizeof(pm_integer_t) + integer->length * sizeof(pm_integer_word_t); +} + +/** + * Recursively destroy the linked list of an integer. + */ +static void +pm_integer_word_destroy(pm_integer_word_t *integer) { + if (integer->next != NULL) { + pm_integer_word_destroy(integer->next); + } + + free(integer); +} + +/** + * Free the internal memory of an integer. This memory will only be allocated if + * the integer exceeds the size of a single node in the linked list. + */ +PRISM_EXPORTED_FUNCTION void +pm_integer_free(pm_integer_t *integer) { + if (integer->head.next) { + pm_integer_word_destroy(integer->head.next); + } +} diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h new file mode 100644 index 00000000000000..5525adabb03bb8 --- /dev/null +++ b/prism/util/pm_integer.h @@ -0,0 +1,104 @@ +/** + * @file pm_integer.h + * + * This module provides functions for working with arbitrary-sized integers. + */ +#ifndef PRISM_NUMBER_H +#define PRISM_NUMBER_H + +#include "prism/defines.h" + +#include +#include +#include +#include + +/** + * A node in the linked list of a pm_integer_t. + */ +typedef struct pm_integer_word { + /** A pointer to the next node in the list. */ + struct pm_integer_word *next; + + /** The value of the node. */ + uint32_t value; +} pm_integer_word_t; + +/** + * This structure represents an arbitrary-sized integer. It is implemented as a + * linked list of 32-bit integers, with the least significant digit at the head + * of the list. + */ +typedef struct { + /** The number of nodes in the linked list that have been allocated. */ + size_t length; + + /** + * The head of the linked list, embedded directly so that allocations do not + * need to be performed for small integers. + */ + pm_integer_word_t head; + + /** + * Whether or not the integer is negative. It is stored this way so that a + * zeroed pm_integer_t is always positive zero. + */ + bool negative; +} pm_integer_t; + +/** + * An enum controlling the base of an integer. It is expected that the base is + * already known before parsing the integer, even though it could be derived + * from the string itself. + */ +typedef enum { + /** The binary base, indicated by a 0b or 0B prefix. */ + PM_INTEGER_BASE_BINARY, + + /** The octal base, indicated by a 0, 0o, or 0O prefix. */ + PM_INTEGER_BASE_OCTAL, + + /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ + PM_INTEGER_BASE_DECIMAL, + + /** The hexidecimal base, indicated by a 0x or 0X prefix. */ + PM_INTEGER_BASE_HEXADECIMAL, + + /** + * An unknown base, in which case pm_integer_parse will derive it based on + * the content of the string. This is less efficient and does more + * comparisons, so if callers know the base ahead of time, they should use + * that instead. + */ + PM_INTEGER_BASE_UNKNOWN +} pm_integer_base_t; + +/** + * Parse an integer from a string. This assumes that the format of the integer + * has already been validated, as internal validation checks are not performed + * here. + * + * @param integer The integer to parse into. + * @param base The base of the integer. + * @param start The start of the string. + * @param end The end of the string. + */ +PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end); + +/** + * Return the memory size of the integer. + * + * @param integer The integer to get the memory size of. + * @return The size of the memory associated with the integer. + */ +size_t pm_integer_memsize(const pm_integer_t *integer); + +/** + * Free the internal memory of an integer. This memory will only be allocated if + * the integer exceeds the size of a single node in the linked list. + * + * @param integer The integer to free. + */ +PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer); + +#endif diff --git a/prism/util/pm_number.c b/prism/util/pm_number.c deleted file mode 100644 index 6f0a13ae8eb4d5..00000000000000 --- a/prism/util/pm_number.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "prism/util/pm_number.h" - -/** - * Create a new node for a number in the linked list. - */ -static pm_number_node_t * -pm_number_node_create(pm_number_t *number, uint32_t value) { - number->length++; - pm_number_node_t *node = malloc(sizeof(pm_number_node_t)); - *node = (pm_number_node_t) { .next = NULL, .value = value }; - return node; -} - -/** - * Add a 32-bit integer to a number. - */ -static void -pm_number_add(pm_number_t *number, uint32_t addend) { - uint32_t carry = addend; - pm_number_node_t *current = &number->head; - - while (carry > 0) { - uint64_t result = (uint64_t) current->value + carry; - carry = (uint32_t) (result >> 32); - current->value = (uint32_t) result; - - if (carry > 0) { - if (current->next == NULL) { - current->next = pm_number_node_create(number, carry); - break; - } - - current = current->next; - } - } -} - -/** - * Multiple a number by a 32-bit integer. In practice, the multiplier is the - * base of the number, so this is 2, 8, 10, or 16. - */ -static void -pm_number_multiply(pm_number_t *number, uint32_t multiplier) { - uint32_t carry = 0; - - for (pm_number_node_t *current = &number->head; current != NULL; current = current->next) { - uint64_t result = (uint64_t) current->value * multiplier + carry; - carry = (uint32_t) (result >> 32); - current->value = (uint32_t) result; - - if (carry > 0 && current->next == NULL) { - current->next = pm_number_node_create(number, carry); - break; - } - } -} - -/** - * Return the value of a digit in a number. - */ -static uint32_t -pm_number_parse_digit(const uint8_t character) { - switch (character) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: assert(false && "unreachable"); - } -} - -/** - * Parse a number from a string. This assumes that the format of the number has - * already been validated, as internal validation checks are not performed here. - */ -PRISM_EXPORTED_FUNCTION void -pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end) { - // Ignore unary +. Unary + is parsed differently and will not end up here. - // Instead, it will modify the parsed number later. - if (*start == '+') start++; - - // Determine the multiplier from the base, and skip past any prefixes. - uint32_t multiplier; - switch (base) { - case PM_NUMBER_BASE_BINARY: - start += 2; // 0b - multiplier = 2; - break; - case PM_NUMBER_BASE_OCTAL: - start++; // 0 - if (*start == 'o' || *start == 'O') start++; // o - multiplier = 8; - break; - case PM_NUMBER_BASE_DECIMAL: - if (*start == '0' && (end - start) > 1) start += 2; // 0d - multiplier = 10; - break; - case PM_NUMBER_BASE_HEXADECIMAL: - start += 2; // 0x - multiplier = 16; - break; - case PM_NUMBER_BASE_UNKNOWN: - if (*start == '0' && (end - start) > 1) { - switch (start[1]) { - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': start++; multiplier = 8; break; - case 'b': case 'B': start += 2; multiplier = 2; break; - case 'o': case 'O': start += 2; multiplier = 8; break; - case 'd': case 'D': start += 2; multiplier = 10; break; - case 'x': case 'X': start += 2; multiplier = 16; break; - default: assert(false && "unreachable"); - } - } else { - multiplier = 10; - } - break; - } - - // It's possible that we've consumed everything at this point if there is an - // invalid number. If this is the case, we'll just return 0. - if (start >= end) return; - - // Add the first digit to the number. - pm_number_add(number, pm_number_parse_digit(*start++)); - - // Add the subsequent digits to the number. - for (; start < end; start++) { - if (*start == '_') continue; - pm_number_multiply(number, multiplier); - pm_number_add(number, pm_number_parse_digit(*start)); - } -} - -/** - * Return the memory size of the number. - */ -size_t -pm_number_memsize(const pm_number_t *number) { - return sizeof(pm_number_t) + number->length * sizeof(pm_number_node_t); -} - -/** - * Recursively destroy the linked list of a number. - */ -static void -pm_number_node_destroy(pm_number_node_t *number) { - if (number->next != NULL) { - pm_number_node_destroy(number->next); - } - - free(number); -} - -/** - * Free the internal memory of a number. This memory will only be allocated if - * the number exceeds the size of a single node in the linked list. - */ -PRISM_EXPORTED_FUNCTION void -pm_number_free(pm_number_t *number) { - if (number->head.next) { - pm_number_node_destroy(number->head.next); - } -} diff --git a/prism/util/pm_number.h b/prism/util/pm_number.h deleted file mode 100644 index 04404ffa0dd642..00000000000000 --- a/prism/util/pm_number.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file pm_number.h - * - * This module provides functions for working with arbitrary-sized numbers. - */ -#ifndef PRISM_NUMBER_H -#define PRISM_NUMBER_H - -#include "prism/defines.h" - -#include -#include -#include -#include - -/** - * A node in the linked list of a pm_number_t. - */ -typedef struct pm_number_node { - /** A pointer to the next node in the list. */ - struct pm_number_node *next; - - /** The value of the node. */ - uint32_t value; -} pm_number_node_t; - -/** - * This structure represents an arbitrary-sized number. It is implemented as a - * linked list of 32-bit integers, with the least significant digit at the head - * of the list. - */ -typedef struct { - /** - * The head of the linked list, embedded directly so that allocations do not - * need to be performed for small numbers. - */ - pm_number_node_t head; - - /** The number of nodes in the linked list that have been allocated. */ - size_t length; - - /** - * Whether or not the number is negative. It is stored this way so that a - * zeroed pm_number_t is always positive zero. - */ - bool negative; -} pm_number_t; - -/** - * An enum controlling the base of a number. It is expected that the base is - * already known before parsing the number, even though it could be derived from - * the string itself. - */ -typedef enum { - /** The binary base, indicated by a 0b or 0B prefix. */ - PM_NUMBER_BASE_BINARY, - - /** The octal base, indicated by a 0, 0o, or 0O prefix. */ - PM_NUMBER_BASE_OCTAL, - - /** The decimal base, indicated by a 0d, 0D, or empty prefix. */ - PM_NUMBER_BASE_DECIMAL, - - /** The hexidecimal base, indicated by a 0x or 0X prefix. */ - PM_NUMBER_BASE_HEXADECIMAL, - - /** - * An unknown base, in which case pm_number_parse will derive it based on - * the content of the string. This is less efficient and does more - * comparisons, so if callers know the base ahead of time, they should use - * that instead. - */ - PM_NUMBER_BASE_UNKNOWN -} pm_number_base_t; - -/** - * Parse a number from a string. This assumes that the format of the number has - * already been validated, as internal validation checks are not performed here. - * - * @param number The number to parse into. - * @param base The base of the number. - * @param start The start of the string. - * @param end The end of the string. - */ -PRISM_EXPORTED_FUNCTION void pm_number_parse(pm_number_t *number, pm_number_base_t base, const uint8_t *start, const uint8_t *end); - -/** - * Return the memory size of the number. - * - * @param number The number to get the memory size of. - * @return The size of the memory associated with the number. - */ -size_t pm_number_memsize(const pm_number_t *number); - -/** - * Free the internal memory of a number. This memory will only be allocated if - * the number exceeds the size of a single node in the linked list. - * - * @param number The number to free. - */ -PRISM_EXPORTED_FUNCTION void pm_number_free(pm_number_t *number); - -#endif diff --git a/test/prism/integer_parse_test.rb b/test/prism/integer_parse_test.rb new file mode 100644 index 00000000000000..756f667b965c5d --- /dev/null +++ b/test/prism/integer_parse_test.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +return if Prism::BACKEND == :FFI + +module Prism + class IntegerParseTest < TestCase + def test_integer_parse + assert_integer_parse(1) + assert_integer_parse(50) + assert_integer_parse(100) + assert_integer_parse(100, "1_0_0") + assert_integer_parse(8, "0_1_0") + + assert_integer_parse(10, "0b1010") + assert_integer_parse(10, "0B1010") + assert_integer_parse(10, "0o12") + assert_integer_parse(10, "0O12") + assert_integer_parse(10, "012") + assert_integer_parse(10, "0d10") + assert_integer_parse(10, "0D10") + assert_integer_parse(10, "0xA") + assert_integer_parse(10, "0XA") + + assert_integer_parse(2**32) + assert_integer_parse(2**64 + 2**32) + assert_integer_parse(2**128 + 2**64 + 2**32) + end + + private + + def assert_integer_parse(expected, source = expected.to_s) + assert_equal expected, Debug.integer_parse(source) + end + end +end diff --git a/test/prism/number_parse_test.rb b/test/prism/number_parse_test.rb deleted file mode 100644 index 401aead243fb20..00000000000000 --- a/test/prism/number_parse_test.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -require_relative "test_helper" - -return if Prism::BACKEND == :FFI - -module Prism - class NumberParseTest < TestCase - def test_number_parse - assert_number_parse(1) - assert_number_parse(50) - assert_number_parse(100) - assert_number_parse(100, "1_0_0") - - assert_number_parse(10, "0b1010") - assert_number_parse(10, "0B1010") - assert_number_parse(10, "0o12") - assert_number_parse(10, "0O12") - assert_number_parse(10, "012") - assert_number_parse(10, "0d10") - assert_number_parse(10, "0D10") - assert_number_parse(10, "0xA") - assert_number_parse(10, "0XA") - - assert_number_parse(2**32) - assert_number_parse(2**64 + 2**32) - assert_number_parse(2**128 + 2**64 + 2**32) - end - - private - - def assert_number_parse(expected, source = expected.to_s) - assert_equal expected, Debug.number_parse(source) - end - end -end diff --git a/test/prism/snapshots/alias.txt b/test/prism/snapshots/alias.txt index c2ddc9d2da8ea4..687082d85e2e31 100644 --- a/test/prism/snapshots/alias.txt +++ b/test/prism/snapshots/alias.txt @@ -68,7 +68,8 @@ │ │ │ │ @ StatementsNode (location: (7,13)-(7,14)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (7,13)-(7,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (7,14)-(7,15) = "}" │ │ └── closing_loc: (7,15)-(7,16) = "\"" │ ├── old_name: diff --git a/test/prism/snapshots/arithmetic.txt b/test/prism/snapshots/arithmetic.txt index b5fca695064d76..c8a31c3d70e54e 100644 --- a/test/prism/snapshots/arithmetic.txt +++ b/test/prism/snapshots/arithmetic.txt @@ -218,7 +218,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (11,1)-(11,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :** │ │ ├── message_loc: (11,2)-(11,4) = "**" @@ -228,7 +229,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -242,7 +244,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (13,0)-(13,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -1 ├── call_operator_loc: (13,2)-(13,3) = "." ├── name: :zero? ├── message_loc: (13,3)-(13,8) = "zero?" diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt index 0cd77eab296965..1cf6b2269722df 100644 --- a/test/prism/snapshots/arrays.txt +++ b/test/prism/snapshots/arrays.txt @@ -66,11 +66,14 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 3) │ │ │ ├── @ IntegerNode (location: (3,16)-(3,17)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (3,19)-(3,20)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (3,22)-(3,23)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ ├── closing_loc: (3,12)-(3,13) = "]" @@ -132,7 +135,8 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ ├── @ IntegerNode (location: (10,3)-(10,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ SymbolNode (location: (14,0)-(14,2)) │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (14,0)-(14,1) = ":" @@ -163,7 +167,8 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ ├── @ IntegerNode (location: (19,3)-(19,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ SymbolNode (location: (23,0)-(23,2)) │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (23,0)-(23,1) = ":" @@ -448,7 +453,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (41,4)-(41,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ ├── closing_loc: (41,5)-(41,6) = "]" │ │ │ └── block: ∅ │ │ └── @ IndexTargetNode (location: (41,8)-(41,14)) @@ -470,7 +476,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (41,12)-(41,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 0 │ │ ├── closing_loc: (41,13)-(41,14) = "]" │ │ └── block: ∅ │ ├── rest: ∅ @@ -483,9 +490,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (41,17)-(41,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (41,20)-(41,21)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ CallNode (location: (43,0)-(43,19)) @@ -670,7 +679,8 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (53,1)-(53,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (53,4)-(53,8)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) @@ -693,7 +703,8 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (55,1)-(55,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (55,4)-(55,20)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) @@ -953,7 +964,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (84,12)-(84,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (84,8)-(84,9) = "]" │ └── block: │ @ BlockArgumentNode (location: (84,4)-(84,8)) @@ -1001,7 +1013,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (86,16)-(86,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (86,12)-(86,13) = "]" │ └── block: │ @ BlockArgumentNode (location: (86,8)-(86,12)) @@ -1060,7 +1073,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (89,11)-(89,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (89,7)-(89,8) = "]" │ │ └── block: │ │ @ BlockArgumentNode (location: (89,6)-(89,7)) @@ -1095,7 +1109,8 @@ │ ├── operator_loc: (92,6)-(92,8) = "+=" │ └── value: │ @ IntegerNode (location: (92,9)-(92,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (94,0)-(94,11)) │ ├── flags: ∅ │ ├── receiver: @@ -1117,7 +1132,8 @@ │ ├── operator_loc: (94,6)-(94,9) = "||=" │ └── value: │ @ IntegerNode (location: (94,10)-(94,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (96,0)-(96,11)) │ ├── flags: ∅ │ ├── receiver: @@ -1139,7 +1155,8 @@ │ ├── operator_loc: (96,6)-(96,9) = "&&=" │ └── value: │ @ IntegerNode (location: (96,10)-(96,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (98,0)-(98,14)) │ ├── flags: ∅ │ ├── receiver: @@ -1172,7 +1189,8 @@ │ ├── operator_loc: (98,10)-(98,12) = "+=" │ └── value: │ @ IntegerNode (location: (98,13)-(98,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (100,0)-(100,15)) │ ├── flags: ∅ │ ├── receiver: @@ -1204,7 +1222,8 @@ │ ├── operator_loc: (100,10)-(100,13) = "||=" │ └── value: │ @ IntegerNode (location: (100,14)-(100,15)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (102,0)-(102,15)) │ ├── flags: ∅ │ ├── receiver: @@ -1236,7 +1255,8 @@ │ ├── operator_loc: (102,10)-(102,13) = "&&=" │ └── value: │ @ IntegerNode (location: (102,14)-(102,15)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (104,0)-(104,13)) │ ├── flags: ∅ │ ├── receiver: @@ -1272,7 +1292,8 @@ │ ├── operator_loc: (104,9)-(104,11) = "+=" │ └── value: │ @ IntegerNode (location: (104,12)-(104,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (106,0)-(106,14)) │ ├── flags: ∅ │ ├── receiver: @@ -1307,7 +1328,8 @@ │ ├── operator_loc: (106,9)-(106,12) = "||=" │ └── value: │ @ IntegerNode (location: (106,13)-(106,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (108,0)-(108,14)) │ ├── flags: ∅ │ ├── receiver: @@ -1342,7 +1364,8 @@ │ ├── operator_loc: (108,9)-(108,12) = "&&=" │ └── value: │ @ IntegerNode (location: (108,13)-(108,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (110,0)-(110,17)) │ ├── flags: ∅ │ ├── receiver: @@ -1388,7 +1411,8 @@ │ ├── operator_loc: (110,13)-(110,15) = "+=" │ └── value: │ @ IntegerNode (location: (110,16)-(110,17)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (112,0)-(112,18)) │ ├── flags: ∅ │ ├── receiver: @@ -1433,7 +1457,8 @@ │ ├── operator_loc: (112,13)-(112,16) = "||=" │ └── value: │ @ IntegerNode (location: (112,17)-(112,18)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (114,0)-(114,18)) │ ├── flags: ∅ │ ├── receiver: @@ -1478,7 +1503,8 @@ │ ├── operator_loc: (114,13)-(114,16) = "&&=" │ └── value: │ @ IntegerNode (location: (114,17)-(114,18)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (116,0)-(116,19)) │ ├── flags: ∅ │ ├── receiver: @@ -1527,7 +1553,8 @@ │ ├── operator_loc: (116,15)-(116,17) = "+=" │ └── value: │ @ IntegerNode (location: (116,18)-(116,19)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (118,0)-(118,20)) │ ├── flags: ∅ │ ├── receiver: @@ -1575,7 +1602,8 @@ │ ├── operator_loc: (118,15)-(118,18) = "||=" │ └── value: │ @ IntegerNode (location: (118,19)-(118,20)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (120,0)-(120,20)) │ ├── flags: ∅ │ ├── receiver: @@ -1623,7 +1651,8 @@ │ ├── operator_loc: (120,15)-(120,18) = "&&=" │ └── value: │ @ IntegerNode (location: (120,19)-(120,20)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOperatorWriteNode (location: (122,0)-(122,23)) │ ├── flags: ∅ │ ├── receiver: @@ -1682,7 +1711,8 @@ │ ├── operator_loc: (122,19)-(122,21) = "+=" │ └── value: │ @ IntegerNode (location: (122,22)-(122,23)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexOrWriteNode (location: (124,0)-(124,24)) │ ├── flags: ∅ │ ├── receiver: @@ -1740,7 +1770,8 @@ │ ├── operator_loc: (124,19)-(124,22) = "||=" │ └── value: │ @ IntegerNode (location: (124,23)-(124,24)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IndexAndWriteNode (location: (126,0)-(126,24)) │ ├── flags: ∅ │ ├── receiver: @@ -1798,7 +1829,8 @@ │ ├── operator_loc: (126,19)-(126,22) = "&&=" │ └── value: │ @ IntegerNode (location: (126,23)-(126,24)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ DefNode (location: (128,0)-(128,19)) │ ├── name: :f │ ├── name_loc: (128,4)-(128,5) = "f" @@ -1896,7 +1928,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (130,12)-(130,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ SplatNode (location: (130,15)-(130,16)) │ │ │ ├── operator_loc: (130,15)-(130,16) = "*" │ │ │ └── expression: ∅ @@ -1955,7 +1988,8 @@ │ │ │ │ ├── operator_loc: (132,12)-(132,13) = "*" │ │ │ │ └── expression: ∅ │ │ │ └── @ IntegerNode (location: (132,17)-(132,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (132,13)-(132,14) = "]" │ │ └── block: ∅ │ ├── locals: [] @@ -2008,12 +2042,14 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (134,12)-(134,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ SplatNode (location: (134,15)-(134,16)) │ │ │ │ ├── operator_loc: (134,15)-(134,16) = "*" │ │ │ │ └── expression: ∅ │ │ │ └── @ IntegerNode (location: (134,20)-(134,21)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (134,16)-(134,17) = "]" │ │ └── block: ∅ │ ├── locals: [] @@ -2072,7 +2108,8 @@ │ │ ├── operator_loc: (136,15)-(136,17) = "+=" │ │ └── value: │ │ @ IntegerNode (location: (136,18)-(136,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (136,0)-(136,3) = "def" │ ├── operator_loc: ∅ @@ -2121,7 +2158,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (138,12)-(138,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ SplatNode (location: (138,15)-(138,16)) │ │ │ ├── operator_loc: (138,15)-(138,16) = "*" │ │ │ └── expression: ∅ @@ -2130,7 +2168,8 @@ │ │ ├── operator_loc: (138,18)-(138,21) = "&&=" │ │ └── value: │ │ @ IntegerNode (location: (138,22)-(138,23)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (138,0)-(138,3) = "def" │ ├── operator_loc: ∅ @@ -2248,7 +2287,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (142,22)-(142,23)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── @ SplatNode (location: (142,25)-(142,26)) │ │ │ │ ├── operator_loc: (142,25)-(142,26) = "*" │ │ │ │ └── expression: ∅ diff --git a/test/prism/snapshots/blocks.txt b/test/prism/snapshots/blocks.txt index 52a7b3990d46a8..0b1ec52e38bb1e 100644 --- a/test/prism/snapshots/blocks.txt +++ b/test/prism/snapshots/blocks.txt @@ -127,7 +127,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,9)-(7,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── closing_loc: (7,10)-(7,11) = ")" │ └── block: │ @ BlockNode (location: (7,12)-(7,35)) @@ -345,7 +346,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (17,14)-(17,15)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── closing_loc: (17,15)-(17,16) = "]" │ │ │ │ └── block: ∅ │ │ │ ├── rest: ∅ @@ -520,7 +522,8 @@ │ │ │ │ ├── operator_loc: (33,12)-(33,13) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (33,14)-(33,15)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) @@ -579,7 +582,8 @@ │ ├── name_loc: (37,0)-(37,4) = "fork" │ ├── value: │ │ @ IntegerNode (location: (37,7)-(37,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (37,5)-(37,6) = "=" ├── @ CallNode (location: (38,0)-(39,3)) │ ├── flags: ignore_visibility @@ -715,14 +719,16 @@ │ │ │ │ │ │ ├── name_loc: (49,2)-(49,4) = "a:" │ │ │ │ │ │ └── value: │ │ │ │ │ │ @ IntegerNode (location: (49,5)-(49,6)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ OptionalKeywordParameterNode (location: (50,2)-(50,6)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ ├── name_loc: (50,2)-(50,4) = "b:" │ │ │ │ │ └── value: │ │ │ │ │ @ IntegerNode (location: (50,5)-(50,6)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 2 │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── locals: (length: 0) diff --git a/test/prism/snapshots/break.txt b/test/prism/snapshots/break.txt index b7d891f0d69e3d..984b9f7f227272 100644 --- a/test/prism/snapshots/break.txt +++ b/test/prism/snapshots/break.txt @@ -16,7 +16,8 @@ │ │ │ │ @ StatementsNode (location: (3,7)-(3,8)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,7)-(3,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (3,6)-(3,7) = "(" │ │ │ └── closing_loc: (3,8)-(3,9) = ")" │ │ ├── @ ParenthesesNode (location: (3,11)-(3,14)) @@ -24,7 +25,8 @@ │ │ │ │ @ StatementsNode (location: (3,12)-(3,13)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,12)-(3,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: (3,11)-(3,12) = "(" │ │ │ └── closing_loc: (3,13)-(3,14) = ")" │ │ └── @ ParenthesesNode (location: (3,16)-(3,19)) @@ -32,7 +34,8 @@ │ │ │ @ StatementsNode (location: (3,17)-(3,18)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,17)-(3,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (3,16)-(3,17) = "(" │ │ └── closing_loc: (3,18)-(3,19) = ")" │ └── keyword_loc: (3,0)-(3,5) = "break" @@ -42,7 +45,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── keyword_loc: (5,0)-(5,5) = "break" ├── @ BreakNode (location: (7,0)-(8,1)) │ ├── arguments: @@ -50,11 +54,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (7,6)-(7,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (7,9)-(7,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (8,0)-(8,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── keyword_loc: (7,0)-(7,5) = "break" ├── @ BreakNode (location: (10,0)-(10,13)) │ ├── arguments: @@ -62,11 +69,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (10,6)-(10,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (10,9)-(10,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (10,12)-(10,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── keyword_loc: (10,0)-(10,5) = "break" ├── @ BreakNode (location: (12,0)-(12,15)) │ ├── arguments: @@ -77,11 +87,14 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 3) │ │ │ ├── @ IntegerNode (location: (12,7)-(12,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (12,10)-(12,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (12,13)-(12,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (12,6)-(12,7) = "[" │ │ └── closing_loc: (12,14)-(12,15) = "]" │ └── keyword_loc: (12,0)-(12,5) = "break" @@ -95,9 +108,11 @@ │ │ │ @ StatementsNode (location: (15,2)-(16,3)) │ │ │ └── body: (length: 2) │ │ │ ├── @ IntegerNode (location: (15,2)-(15,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (14,5)-(14,6) = "(" │ │ └── closing_loc: (17,0)-(17,1) = ")" │ └── keyword_loc: (14,0)-(14,5) = "break" @@ -121,7 +136,8 @@ │ │ │ @ StatementsNode (location: (21,6)-(21,7)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (21,6)-(21,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (21,5)-(21,6) = "(" │ │ └── closing_loc: (21,7)-(21,8) = ")" │ └── keyword_loc: (21,0)-(21,5) = "break" @@ -150,7 +166,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (23,12)-(23,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── keyword_loc: (23,6)-(23,11) = "break" │ │ ├── opening_loc: (23,4)-(23,5) = "{" │ │ └── closing_loc: (23,15)-(23,16) = "}" @@ -163,7 +180,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,20)-(23,22)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (25,0)-(25,23)) @@ -215,6 +233,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (25,21)-(25,23)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/case.txt b/test/prism/snapshots/case.txt index b74ff535e04b40..a2c6bac0a9b3ec 100644 --- a/test/prism/snapshots/case.txt +++ b/test/prism/snapshots/case.txt @@ -269,7 +269,8 @@ │ │ ├── keyword_loc: (32,14)-(32,18) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (32,19)-(32,20)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── statements: ∅ │ ├── consequent: ∅ │ ├── case_keyword_loc: (32,0)-(32,4) = "case" @@ -279,17 +280,20 @@ │ │ @ MatchPredicateNode (location: (34,5)-(34,11)) │ │ ├── value: │ │ │ @ IntegerNode (location: (34,5)-(34,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (34,10)-(34,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (34,7)-(34,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (35,0)-(35,6)) │ │ ├── keyword_loc: (35,0)-(35,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (35,5)-(35,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ └── statements: ∅ │ ├── consequent: ∅ │ ├── case_keyword_loc: (34,0)-(34,4) = "case" @@ -299,17 +303,20 @@ │ │ @ MatchPredicateNode (location: (38,5)-(38,11)) │ │ ├── value: │ │ │ @ IntegerNode (location: (38,5)-(38,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (38,10)-(38,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (38,7)-(38,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ WhenNode (location: (38,13)-(38,19)) │ │ ├── keyword_loc: (38,13)-(38,17) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ IntegerNode (location: (38,18)-(38,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ └── statements: ∅ │ ├── consequent: ∅ │ ├── case_keyword_loc: (38,0)-(38,4) = "case" @@ -319,16 +326,19 @@ │ │ @ MatchPredicateNode (location: (40,5)-(40,11)) │ │ ├── value: │ │ │ @ IntegerNode (location: (40,5)-(40,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (40,10)-(40,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (40,7)-(40,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (41,0)-(41,4)) │ │ ├── pattern: │ │ │ @ IntegerNode (location: (41,3)-(41,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── statements: ∅ │ │ ├── in_loc: (41,0)-(41,2) = "in" │ │ └── then_loc: ∅ @@ -340,16 +350,19 @@ │ │ @ MatchPredicateNode (location: (44,5)-(44,11)) │ │ ├── value: │ │ │ @ IntegerNode (location: (44,5)-(44,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ IntegerNode (location: (44,10)-(44,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (44,7)-(44,9) = "in" │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (44,13)-(44,17)) │ │ ├── pattern: │ │ │ @ IntegerNode (location: (44,16)-(44,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── statements: ∅ │ │ ├── in_loc: (44,13)-(44,15) = "in" │ │ └── then_loc: ∅ @@ -429,7 +442,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (51,0)-(51,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: (51,1)-(51,2) = "." ├── name: :then ├── message_loc: (51,2)-(51,6) = "then" @@ -448,7 +462,8 @@ │ └── @ CaseMatchNode (location: (52,2)-(54,5)) │ ├── predicate: │ │ @ IntegerNode (location: (52,7)-(52,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── conditions: (length: 1) │ │ └── @ InNode (location: (53,2)-(53,8)) │ │ ├── pattern: diff --git a/test/prism/snapshots/classes.txt b/test/prism/snapshots/classes.txt index a6544d52bce15e..4a36bd5cdc49e5 100644 --- a/test/prism/snapshots/classes.txt +++ b/test/prism/snapshots/classes.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,8)-(1,9) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,10)-(1,11) = "=" │ ├── end_keyword_loc: (1,14)-(1,17) = "end" │ └── name: :A @@ -98,7 +99,8 @@ │ │ ├── name_loc: (8,0)-(8,1) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (8,4)-(8,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (8,2)-(8,3) = "=" │ ├── end_keyword_loc: (9,0)-(9,3) = "end" │ └── name: :A @@ -287,7 +289,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ │ │ ├── message_loc: (29,2)-(29,3) = "+" @@ -297,7 +300,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (29,4)-(29,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── end_keyword_loc: (30,0)-(30,3) = "end" @@ -314,7 +318,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (32,14)-(32,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ │ │ ├── message_loc: (32,16)-(32,17) = "+" @@ -324,7 +329,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (32,18)-(32,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── end_keyword_loc: (32,20)-(32,23) = "end" @@ -350,7 +356,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (34,12)-(34,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (34,13)-(34,14) = "]" │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/command_method_call.txt b/test/prism/snapshots/command_method_call.txt index de6093abbd15fc..7fd6341304c950 100644 --- a/test/prism/snapshots/command_method_call.txt +++ b/test/prism/snapshots/command_method_call.txt @@ -15,7 +15,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,9)) @@ -41,7 +42,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,8)-(3,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ @@ -61,7 +63,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,13)-(5,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ @@ -80,7 +83,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,4)-(5,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── consequent: ∅ @@ -100,7 +104,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,17)-(7,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── then_keyword_loc: ∅ @@ -119,7 +124,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,4)-(7,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── consequent: ∅ @@ -141,7 +147,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (9,16)-(9,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── statements: @@ -159,7 +166,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (9,4)-(9,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ UntilNode (location: (11,0)-(11,17)) @@ -179,7 +187,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (11,16)-(11,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── statements: @@ -197,7 +206,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RescueModifierNode (location: (13,0)-(13,18)) @@ -214,7 +224,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (13,4)-(13,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (13,6)-(13,12) = "rescue" @@ -231,7 +242,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,17)-(13,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,10)) @@ -267,7 +279,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (15,8)-(15,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: (15,9)-(15,10) = "]" @@ -286,7 +299,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,4)-(17,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── right: @@ -302,7 +316,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,14)-(17,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── operator_loc: (17,6)-(17,9) = "and" @@ -320,7 +335,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (19,4)-(19,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── right: @@ -336,7 +352,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (19,13)-(19,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── operator_loc: (19,6)-(19,8) = "or" @@ -355,7 +372,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (21,8)-(21,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -387,7 +405,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (23,16)-(23,17)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── operator_loc: (23,10)-(23,11) = "=" @@ -412,7 +431,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (25,14)-(25,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [] @@ -426,7 +446,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (27,0)-(27,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: (27,1)-(27,2) = "." │ ├── name: :foo │ ├── message_loc: (27,2)-(27,5) = "foo" @@ -436,7 +457,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,6)-(27,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,11)) @@ -446,7 +468,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: (29,1)-(29,2) = "." │ │ ├── name: :foo │ │ ├── message_loc: (29,2)-(29,5) = "foo" @@ -463,7 +486,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,10)-(29,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,14)) @@ -476,7 +500,8 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (31,0)-(31,1)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: (31,1)-(31,2) = "." │ │ │ ├── name: :foo │ │ │ ├── message_loc: (31,2)-(31,5) = "foo" @@ -493,7 +518,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (31,6)-(31,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: (31,7)-(31,8) = "]" │ │ └── block: ∅ │ ├── call_operator_loc: (31,8)-(31,9) = "." @@ -505,7 +531,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,13)-(31,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,14)) @@ -515,7 +542,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: (33,1)-(33,2) = "." │ │ ├── name: :foo │ │ ├── message_loc: (33,2)-(33,5) = "foo" @@ -525,7 +553,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (33,6)-(33,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: (33,7)-(33,8) = ")" │ │ └── block: ∅ │ ├── call_operator_loc: (33,8)-(33,9) = "." @@ -537,7 +566,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,13)-(33,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,15)) @@ -547,7 +577,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: (35,1)-(35,2) = "." │ │ ├── name: :foo │ │ ├── message_loc: (35,2)-(35,5) = "foo" @@ -558,7 +589,8 @@ │ │ @ BlockArgumentNode (location: (35,6)-(35,8)) │ │ ├── expression: │ │ │ @ IntegerNode (location: (35,7)-(35,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (35,6)-(35,7) = "&" │ ├── call_operator_loc: (35,9)-(35,10) = "." │ ├── name: :bar @@ -569,7 +601,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,14)-(35,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ AndNode (location: (37,0)-(37,17)) @@ -589,7 +622,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (37,5)-(37,6)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── call_operator_loc: ∅ @@ -615,7 +649,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (37,16)-(37,17)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── call_operator_loc: ∅ @@ -643,7 +678,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (39,5)-(39,6)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── call_operator_loc: ∅ @@ -669,7 +705,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (39,15)-(39,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── call_operator_loc: ∅ @@ -698,7 +735,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (41,9)-(41,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ diff --git a/test/prism/snapshots/constants.txt b/test/prism/snapshots/constants.txt index 744a081c067ada..59e234148a5add 100644 --- a/test/prism/snapshots/constants.txt +++ b/test/prism/snapshots/constants.txt @@ -54,13 +54,15 @@ │ ├── operator_loc: (7,5)-(7,6) = "=" │ └── value: │ @ IntegerNode (location: (7,7)-(7,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ConstantWriteNode (location: (9,0)-(9,5)) │ ├── name: :A │ ├── name_loc: (9,0)-(9,1) = "A" │ ├── value: │ │ @ IntegerNode (location: (9,4)-(9,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (9,2)-(9,3) = "=" ├── @ ConstantReadNode (location: (11,0)-(11,3)) │ └── name: :ABC @@ -76,7 +78,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,4)-(13,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,8)) @@ -268,7 +271,8 @@ │ ├── operator_loc: (29,4)-(29,5) = "=" │ └── value: │ @ IntegerNode (location: (29,6)-(29,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ConstantPathWriteNode (location: (31,0)-(31,10)) │ ├── target: │ │ @ ConstantPathNode (location: (31,0)-(31,6)) @@ -286,7 +290,8 @@ │ ├── operator_loc: (31,7)-(31,8) = "=" │ └── value: │ @ IntegerNode (location: (31,9)-(31,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ConstantPathNode (location: (33,0)-(33,6)) │ ├── parent: │ │ @ ConstantPathNode (location: (33,0)-(33,3)) diff --git a/test/prism/snapshots/dash_heredocs.txt b/test/prism/snapshots/dash_heredocs.txt index 80f54aefa8b9a6..9af3acf9c2e6e8 100644 --- a/test/prism/snapshots/dash_heredocs.txt +++ b/test/prism/snapshots/dash_heredocs.txt @@ -198,7 +198,8 @@ │ │ │ │ │ @ StatementsNode (location: (53,4)-(53,5)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (53,4)-(53,5)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 2 │ │ │ │ └── closing_loc: (54,2)-(54,3) = "}" │ │ │ └── @ StringNode (location: (54,3)-(55,0)) │ │ │ ├── flags: ∅ @@ -241,7 +242,8 @@ │ │ │ │ @ StatementsNode (location: (62,2)-(62,3)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (62,2)-(62,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── closing_loc: (62,3)-(62,4) = "}" │ │ └── @ StringNode (location: (62,4)-(63,0)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/defined.txt b/test/prism/snapshots/defined.txt index 9c84b0b61120e2..53a5081811c42d 100644 --- a/test/prism/snapshots/defined.txt +++ b/test/prism/snapshots/defined.txt @@ -9,7 +9,8 @@ │ │ ├── lparen_loc: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rparen_loc: ∅ │ │ └── keyword_loc: (1,0)-(1,8) = "defined?" │ ├── right: @@ -17,7 +18,8 @@ │ │ ├── lparen_loc: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (1,24)-(1,25)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── rparen_loc: ∅ │ │ └── keyword_loc: (1,15)-(1,23) = "defined?" │ └── operator_loc: (1,11)-(1,14) = "and" @@ -29,7 +31,8 @@ │ │ ├── operator_loc: (3,11)-(3,13) = "%=" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,14)-(3,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── name: :x │ │ ├── operator: :% │ │ └── depth: 0 @@ -68,7 +71,8 @@ │ ├── lparen_loc: ∅ │ ├── value: │ │ @ IntegerNode (location: (7,9)-(7,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── rparen_loc: ∅ │ └── keyword_loc: (7,0)-(7,8) = "defined?" └── @ DefinedNode (location: (9,0)-(10,1)) diff --git a/test/prism/snapshots/emoji_method_calls.txt b/test/prism/snapshots/emoji_method_calls.txt index a38d1431dad84c..8f71181ac1544a 100644 --- a/test/prism/snapshots/emoji_method_calls.txt +++ b/test/prism/snapshots/emoji_method_calls.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,11)-(1,12)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/endless_methods.txt b/test/prism/snapshots/endless_methods.txt index 7485160a83c592..6e20c0deec6140 100644 --- a/test/prism/snapshots/endless_methods.txt +++ b/test/prism/snapshots/endless_methods.txt @@ -12,7 +12,8 @@ │ │ @ StatementsNode (location: (1,10)-(1,11)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" │ ├── operator_loc: ∅ @@ -69,7 +70,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (5,13)-(5,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+ │ │ ├── message_loc: (5,15)-(5,16) = "+" @@ -79,7 +81,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,17)-(5,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -91,7 +94,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,21)-(5,22)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/endless_range_in_conditional.txt b/test/prism/snapshots/endless_range_in_conditional.txt index eb5b321c94b58f..1802c4faed6cb8 100644 --- a/test/prism/snapshots/endless_range_in_conditional.txt +++ b/test/prism/snapshots/endless_range_in_conditional.txt @@ -10,10 +10,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (1,4)-(1,6) = ".." │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ @@ -27,7 +29,8 @@ │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (2,3)-(2,5) = ".." │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ @@ -40,7 +43,8 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (3,3)-(3,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: ∅ │ └── operator_loc: (3,4)-(3,6) = ".." ├── then_keyword_loc: ∅ diff --git a/test/prism/snapshots/for.txt b/test/prism/snapshots/for.txt index b2aeb8fccf439f..cc4bbc1166fd03 100644 --- a/test/prism/snapshots/for.txt +++ b/test/prism/snapshots/for.txt @@ -13,10 +13,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ └── operator_loc: (1,10)-(1,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (2,0)-(2,1)) @@ -38,10 +40,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (5,9)-(5,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (5,12)-(5,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ └── operator_loc: (5,10)-(5,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (5,16)-(5,17)) @@ -72,10 +76,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (7,14)-(7,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ └── operator_loc: (7,12)-(7,14) = ".." │ ├── statements: │ │ @ StatementsNode (location: (8,0)-(8,1)) @@ -109,10 +115,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (11,13)-(11,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (11,16)-(11,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ └── operator_loc: (11,14)-(11,16) = ".." │ ├── statements: │ │ @ StatementsNode (location: (12,0)-(12,1)) @@ -134,10 +142,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (15,9)-(15,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (15,12)-(15,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ └── operator_loc: (15,10)-(15,12) = ".." │ ├── statements: │ │ @ StatementsNode (location: (16,0)-(16,1)) @@ -159,10 +169,12 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (19,9)-(19,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (19,12)-(19,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator_loc: (19,10)-(19,12) = ".." ├── statements: │ @ StatementsNode (location: (19,16)-(19,17)) diff --git a/test/prism/snapshots/hashes.txt b/test/prism/snapshots/hashes.txt index 5fd0636548ef5f..7a3ac4b0eaaf22 100644 --- a/test/prism/snapshots/hashes.txt +++ b/test/prism/snapshots/hashes.txt @@ -265,7 +265,8 @@ │ ├── name_loc: (22,0)-(22,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (22,4)-(22,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (22,2)-(22,3) = "=" ├── @ CallNode (location: (23,0)-(26,3)) │ ├── flags: ignore_visibility @@ -289,7 +290,8 @@ │ │ │ ├── name_loc: (24,2)-(24,3) = "b" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (24,6)-(24,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (24,4)-(24,5) = "=" │ │ └── @ HashNode (location: (25,2)-(25,20)) │ │ ├── opening_loc: (25,2)-(25,3) = "{" @@ -376,6 +378,7 @@ │ │ └── unescaped: "a" │ ├── value: │ │ @ IntegerNode (location: (28,5)-(28,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: -1 │ └── operator_loc: ∅ └── closing_loc: (28,8)-(28,9) = "}" diff --git a/test/prism/snapshots/heredocs_nested.txt b/test/prism/snapshots/heredocs_nested.txt index e49e7df97a3363..1717aadbbce9c8 100644 --- a/test/prism/snapshots/heredocs_nested.txt +++ b/test/prism/snapshots/heredocs_nested.txt @@ -62,7 +62,8 @@ │ │ │ │ │ │ │ │ │ @ StatementsNode (location: (17,2)-(17,3)) │ │ │ │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ │ │ │ └── @ IntegerNode (location: (17,2)-(17,3)) - │ │ │ │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ │ │ │ └── value: 3 │ │ │ │ │ │ │ │ └── closing_loc: (17,3)-(17,4) = "}" │ │ │ │ │ │ │ └── @ StringNode (location: (17,4)-(18,0)) │ │ │ │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/if.txt b/test/prism/snapshots/if.txt index 476088de72ac7c..f879ed38857a8e 100644 --- a/test/prism/snapshots/if.txt +++ b/test/prism/snapshots/if.txt @@ -12,7 +12,8 @@ │ │ @ StatementsNode (location: (1,9)-(1,10)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: ∅ │ └── end_keyword_loc: (1,12)-(1,15) = "end" ├── @ IfNode (location: (3,0)-(4,12)) @@ -24,7 +25,8 @@ │ │ @ StatementsNode (location: (4,0)-(4,1)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (4,0)-(4,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: │ │ @ ElseNode (location: (4,2)-(4,12)) │ │ ├── else_keyword_loc: (4,2)-(4,6) = "else" @@ -32,7 +34,8 @@ │ │ │ @ StatementsNode (location: (4,7)-(4,8)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (4,7)-(4,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: (4,9)-(4,12) = "end" │ └── end_keyword_loc: (4,9)-(4,12) = "end" ├── @ IfNode (location: (6,0)-(6,73)) @@ -84,7 +87,8 @@ │ │ @ StatementsNode (location: (8,0)-(8,1)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,0)-(8,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: ∅ │ └── end_keyword_loc: ∅ ├── @ IfNode (location: (10,0)-(10,13)) @@ -149,7 +153,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (16,24)-(16,26)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── keyword_loc: (16,18)-(16,23) = "break" │ ├── consequent: ∅ │ └── end_keyword_loc: (16,27)-(16,30) = "end" @@ -299,7 +304,8 @@ │ │ │ └── block: ∅ │ │ ├── pattern: │ │ │ @ IntegerNode (location: (29,11)-(29,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (29,8)-(29,10) = "in" │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ @@ -332,7 +338,8 @@ ├── if_keyword_loc: (33,0)-(33,2) = "if" ├── predicate: │ @ IntegerNode (location: (33,3)-(33,4)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── then_keyword_loc: ∅ ├── statements: │ @ StatementsNode (location: (34,2)-(35,5)) @@ -374,7 +381,8 @@ │ ├── if_keyword_loc: (36,0)-(36,5) = "elsif" │ ├── predicate: │ │ @ IntegerNode (location: (36,6)-(36,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (37,2)-(38,5)) diff --git a/test/prism/snapshots/integer_operations.txt b/test/prism/snapshots/integer_operations.txt index c8b76cacfacc1c..4660928ad26998 100644 --- a/test/prism/snapshots/integer_operations.txt +++ b/test/prism/snapshots/integer_operations.txt @@ -7,7 +7,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :! │ ├── message_loc: (1,0)-(1,1) = "!" @@ -19,7 +20,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (3,1)-(3,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :~ │ ├── message_loc: (3,0)-(3,1) = "~" @@ -31,7 +33,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (5,0)-(5,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :!= │ ├── message_loc: (5,2)-(5,4) = "!=" @@ -41,14 +44,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,5)-(5,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (7,0)-(7,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (7,0)-(7,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :!~ │ ├── message_loc: (7,2)-(7,4) = "!~" @@ -58,14 +63,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,5)-(7,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (9,0)-(9,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (9,0)-(9,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :% │ ├── message_loc: (9,2)-(9,3) = "%" @@ -75,14 +82,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (9,4)-(9,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (11,0)-(11,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (11,0)-(11,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :& │ ├── message_loc: (11,2)-(11,3) = "&" @@ -92,14 +101,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (13,0)-(13,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (13,0)-(13,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :* │ ├── message_loc: (13,2)-(13,3) = "*" @@ -109,14 +120,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,4)-(13,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,4)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (15,0)-(15,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :** │ ├── message_loc: (15,1)-(15,3) = "**" @@ -126,14 +139,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (15,3)-(15,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (17,0)-(17,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (17,0)-(17,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+ │ ├── message_loc: (17,2)-(17,3) = "+" @@ -143,14 +158,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (17,4)-(17,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (19,0)-(19,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (19,0)-(19,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :- │ ├── message_loc: (19,2)-(19,3) = "-" @@ -160,14 +177,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (19,4)-(19,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (21,0)-(21,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (21,0)-(21,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :/ │ ├── message_loc: (21,2)-(21,3) = "/" @@ -177,7 +196,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (21,4)-(21,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(23,5)) @@ -187,7 +207,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (23,0)-(23,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :/ │ │ ├── message_loc: (23,1)-(23,2) = "/" @@ -197,7 +218,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (23,2)-(23,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -209,14 +231,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,4)-(23,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (25,0)-(25,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :< │ ├── message_loc: (25,2)-(25,3) = "<" @@ -226,14 +250,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (25,4)-(25,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (27,0)-(27,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (27,0)-(27,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :<< │ ├── message_loc: (27,2)-(27,4) = "<<" @@ -243,14 +269,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,5)-(27,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :<= │ ├── message_loc: (29,2)-(29,4) = "<=" @@ -260,14 +288,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,5)-(29,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,7)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (31,0)-(31,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :<=> │ ├── message_loc: (31,2)-(31,5) = "<=>" @@ -277,14 +307,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,6)-(31,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :== │ ├── message_loc: (33,2)-(33,4) = "==" @@ -294,14 +326,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,5)-(33,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,7)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :=== │ ├── message_loc: (35,2)-(35,5) = "===" @@ -311,14 +345,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,6)-(35,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (37,0)-(37,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :=~ │ ├── message_loc: (37,2)-(37,4) = "=~" @@ -328,14 +364,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (37,5)-(37,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (39,0)-(39,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :> │ ├── message_loc: (39,2)-(39,3) = ">" @@ -345,14 +383,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (39,4)-(39,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (41,0)-(41,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :>= │ ├── message_loc: (41,2)-(41,4) = ">=" @@ -362,14 +402,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (41,5)-(41,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (43,0)-(43,6)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (43,0)-(43,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :>> │ ├── message_loc: (43,2)-(43,4) = ">>" @@ -379,14 +421,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (43,5)-(43,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (45,0)-(45,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :^ │ ├── message_loc: (45,2)-(45,3) = "^" @@ -396,14 +440,16 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (45,4)-(45,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (47,0)-(47,5)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (47,0)-(47,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :| │ ├── message_loc: (47,2)-(47,3) = "|" @@ -413,30 +459,36 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (47,4)-(47,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ AndNode (location: (49,0)-(49,6)) │ ├── left: │ │ @ IntegerNode (location: (49,0)-(49,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (49,5)-(49,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (49,2)-(49,4) = "&&" ├── @ AndNode (location: (51,0)-(51,7)) │ ├── left: │ │ @ IntegerNode (location: (51,0)-(51,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (51,6)-(51,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (51,2)-(51,5) = "and" ├── @ CallNode (location: (53,0)-(53,10)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (53,0)-(53,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :* │ ├── message_loc: (53,2)-(53,3) = "*" @@ -449,7 +501,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (53,4)-(53,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :** │ │ ├── message_loc: (53,6)-(53,8) = "**" @@ -459,7 +512,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (53,9)-(53,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ @@ -471,7 +525,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (55,0)-(55,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :* │ │ ├── message_loc: (55,2)-(55,3) = "*" @@ -481,7 +536,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (55,4)-(55,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -493,30 +549,36 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (55,8)-(55,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ OrNode (location: (57,0)-(57,6)) │ ├── left: │ │ @ IntegerNode (location: (57,0)-(57,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (57,5)-(57,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (57,2)-(57,4) = "or" ├── @ OrNode (location: (59,0)-(59,6)) │ ├── left: │ │ @ IntegerNode (location: (59,0)-(59,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (59,5)-(59,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (59,2)-(59,4) = "||" ├── @ CallNode (location: (61,0)-(61,9)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (61,0)-(61,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+ │ ├── message_loc: (61,2)-(61,3) = "+" @@ -529,7 +591,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (61,4)-(61,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :* │ │ ├── message_loc: (61,6)-(61,7) = "*" @@ -539,7 +602,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (61,8)-(61,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ @@ -552,7 +616,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (63,1)-(63,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+ │ ├── message_loc: (63,3)-(63,4) = "+" @@ -562,7 +627,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (63,5)-(63,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── opening_loc: (63,0)-(63,1) = "(" diff --git a/test/prism/snapshots/lambda.txt b/test/prism/snapshots/lambda.txt index 6b50f02af75ef2..f9e82c8811a508 100644 --- a/test/prism/snapshots/lambda.txt +++ b/test/prism/snapshots/lambda.txt @@ -118,7 +118,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (7,10)-(7,11)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 3 │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index 0463d04ab1b025..370686e9ea71a9 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -177,11 +177,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (15,3)-(15,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (15,6)-(15,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (15,9)-(15,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── closing_loc: (15,10)-(15,11) = ")" │ └── block: ∅ ├── @ CallNode (location: (17,0)-(17,4)) @@ -259,7 +262,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (21,10)-(21,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(23,2)) @@ -543,9 +547,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (41,19)-(41,20)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (41,22)-(41,23)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ CallNode (location: (43,0)-(43,4)) @@ -850,7 +856,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (62,3)-(62,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 123 │ │ └── @ HashNode (location: (62,8)-(62,49)) │ │ ├── opening_loc: (62,8)-(62,9) = "{" │ │ ├── elements: (length: 3) @@ -1335,7 +1342,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (89,10)-(89,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (89,13)-(89,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) @@ -1349,7 +1357,8 @@ │ │ │ └── unescaped: "kwarg" │ │ ├── value: │ │ │ @ IntegerNode (location: (89,20)-(89,21)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ @@ -1367,7 +1376,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (91,15)-(91,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ ├── closing_loc: (91,17)-(91,18) = ")" │ └── block: ∅ ├── @ CallNode (location: (93,0)-(93,10)) @@ -1537,7 +1547,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (103,9)-(103,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: -1 │ │ └── operator_loc: ∅ │ ├── closing_loc: (103,11)-(103,12) = ")" │ └── block: ∅ @@ -1845,7 +1856,8 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (117,8)-(117,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: (117,9)-(117,10) = "." │ │ │ ├── name: :times │ │ │ ├── message_loc: (117,10)-(117,15) = "times" @@ -1860,7 +1872,8 @@ │ │ │ │ @ StatementsNode (location: (117,19)-(117,20)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (117,19)-(117,20)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (117,16)-(117,18) = "do" │ │ │ └── closing_loc: (117,21)-(117,24) = "end" │ │ ├── rescue_clause: ∅ @@ -2340,7 +2353,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (151,4)-(151,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ CallNode (location: (151,7)-(151,16)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ @@ -2358,7 +2372,8 @@ │ │ │ @ StatementsNode (location: (151,13)-(151,14)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (151,13)-(151,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (151,11)-(151,12) = "{" │ │ └── closing_loc: (151,15)-(151,16) = "}" │ ├── closing_loc: ∅ @@ -2369,7 +2384,8 @@ │ ├── name_loc: (153,0)-(153,3) = "foo" │ ├── value: │ │ @ IntegerNode (location: (153,6)-(153,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (153,4)-(153,5) = "=" ├── @ CallNode (location: (154,0)-(154,6)) │ ├── flags: ignore_visibility @@ -2433,7 +2449,8 @@ │ │ └── closing_loc: (156,14)-(156,16) = "\":" │ ├── value: │ │ @ IntegerNode (location: (156,17)-(156,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ └── operator_loc: ∅ ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt index a96abf920376ae..ac21bbaed199f0 100644 --- a/test/prism/snapshots/methods.txt +++ b/test/prism/snapshots/methods.txt @@ -63,7 +63,8 @@ │ │ │ ├── operator_loc: (4,29)-(4,30) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (4,31)-(4,32)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ MultiTargetNode (location: (4,34)-(4,44)) @@ -370,7 +371,8 @@ │ ├── name_loc: (44,0)-(44,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (44,4)-(44,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (44,2)-(44,3) = "=" ├── @ DefNode (location: (44,7)-(45,3)) │ ├── name: :a @@ -450,7 +452,8 @@ │ │ │ ├── name_loc: (53,10)-(53,12) = "c:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (53,13)-(53,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ @@ -482,7 +485,8 @@ │ │ │ ├── name_loc: (56,10)-(56,12) = "c:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (56,13)-(56,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ @@ -510,7 +514,8 @@ │ │ │ │ ├── name_loc: (59,6)-(59,8) = "b:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (60,2)-(60,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ RequiredKeywordParameterNode (location: (60,5)-(60,7)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :c @@ -546,7 +551,8 @@ │ │ │ │ ├── operator_loc: (65,8)-(65,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (65,10)-(65,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (65,13)-(65,18)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :c @@ -554,7 +560,8 @@ │ │ │ ├── operator_loc: (65,15)-(65,16) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (65,17)-(65,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -599,7 +606,8 @@ │ │ │ ├── operator_loc: (71,11)-(71,12) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (71,13)-(71,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -738,7 +746,8 @@ │ │ ├── name_loc: (86,0)-(86,1) = "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (86,4)-(86,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (86,2)-(86,3) = "=" │ ├── locals: [:b] │ ├── def_keyword_loc: (85,0)-(85,3) = "def" @@ -840,7 +849,8 @@ │ │ @ StatementsNode (location: (103,10)-(103,11)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (103,10)-(103,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (103,0)-(103,3) = "def" │ ├── operator_loc: ∅ @@ -857,7 +867,8 @@ │ │ @ StatementsNode (location: (104,10)-(104,11)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (104,10)-(104,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── locals: [] │ ├── def_keyword_loc: (104,0)-(104,3) = "def" │ ├── operator_loc: ∅ @@ -885,7 +896,8 @@ │ │ @ StatementsNode (location: (106,15)-(106,18)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (106,15)-(106,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 123 │ ├── locals: [:bar] │ ├── def_keyword_loc: (106,0)-(106,3) = "def" │ ├── operator_loc: ∅ @@ -902,7 +914,8 @@ │ │ @ StatementsNode (location: (108,10)-(108,13)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (108,10)-(108,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 123 │ ├── locals: [] │ ├── def_keyword_loc: (108,0)-(108,3) = "def" │ ├── operator_loc: ∅ @@ -1021,9 +1034,11 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 3) │ │ │ ├── @ IntegerNode (location: (114,14)-(114,15)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (114,17)-(114,18)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ ForwardingArgumentsNode (location: (114,20)-(114,23)) │ │ ├── closing_loc: (114,23)-(114,24) = ")" │ │ └── block: ∅ @@ -1186,7 +1201,8 @@ │ ├── name_loc: (133,0)-(133,5) = "Const" │ ├── value: │ │ @ IntegerNode (location: (133,8)-(133,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (133,6)-(133,7) = "=" ├── @ DefNode (location: (133,11)-(134,3)) │ ├── name: :a @@ -1355,10 +1371,12 @@ │ │ │ │ ├── flags: exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (142,12)-(142,13)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (142,16)-(142,18)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (142,13)-(142,16) = "..." │ │ │ ├── opening_loc: (142,11)-(142,12) = "(" │ │ │ └── closing_loc: (142,18)-(142,19) = ")" @@ -1397,7 +1415,8 @@ │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (145,15)-(145,17)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (145,12)-(145,15) = "..." │ │ │ ├── opening_loc: (145,11)-(145,12) = "(" │ │ │ └── closing_loc: (145,17)-(145,18) = ")" @@ -1435,7 +1454,8 @@ │ │ │ │ ├── flags: exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (148,12)-(148,13)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: ∅ │ │ │ │ └── operator_loc: (148,13)-(148,16) = "..." │ │ │ ├── opening_loc: (148,11)-(148,12) = "(" @@ -1472,10 +1492,12 @@ │ │ │ │ ├── flags: exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (151,13)-(151,14)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (151,17)-(151,19)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (151,14)-(151,17) = "..." │ │ │ ├── opening_loc: (151,12)-(151,13) = "(" │ │ │ └── closing_loc: (151,19)-(151,20) = ")" @@ -1515,7 +1537,8 @@ │ │ │ │ ├── left: ∅ │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (154,16)-(154,18)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 10 │ │ │ │ └── operator_loc: (154,13)-(154,16) = "..." │ │ │ ├── opening_loc: (154,12)-(154,13) = "(" │ │ │ └── closing_loc: (154,18)-(154,19) = ")" @@ -1554,7 +1577,8 @@ │ │ │ │ ├── flags: exclude_end │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (157,13)-(157,14)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: ∅ │ │ │ │ └── operator_loc: (157,14)-(157,17) = "..." │ │ │ ├── opening_loc: (157,12)-(157,13) = "(" @@ -1643,7 +1667,8 @@ │ ├── name_loc: (164,0)-(164,3) = "foo" │ ├── value: │ │ @ IntegerNode (location: (164,6)-(164,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (164,4)-(164,5) = "=" ├── @ DefNode (location: (165,0)-(165,16)) │ ├── name: :bar @@ -1952,7 +1977,8 @@ │ │ │ │ │ ├── equal_loc: (181,28)-(181,29) = "=" │ │ │ │ │ └── end_keyword_loc: ∅ │ │ │ │ └── @ IntegerNode (location: (181,35)-(181,36)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (181,14)-(181,15) = "(" │ │ │ └── closing_loc: (181,36)-(181,37) = ")" │ │ ├── rest: ∅ @@ -1964,7 +1990,8 @@ │ │ @ StatementsNode (location: (181,41)-(181,42)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (181,41)-(181,42)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── locals: [:bar] │ ├── def_keyword_loc: (181,0)-(181,3) = "def" │ ├── operator_loc: ∅ @@ -2002,7 +2029,8 @@ │ │ ├── operator_loc: (183,29)-(183,30) = "=" │ │ └── value: │ │ @ IntegerNode (location: (183,31)-(183,32)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 0) @@ -2012,7 +2040,8 @@ │ @ StatementsNode (location: (183,36)-(183,37)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (183,36)-(183,37)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── locals: [:bar] ├── def_keyword_loc: (183,0)-(183,3) = "def" ├── operator_loc: (183,20)-(183,21) = "." diff --git a/test/prism/snapshots/modules.txt b/test/prism/snapshots/modules.txt index 9b77f39b659bd7..aef3875d74d983 100644 --- a/test/prism/snapshots/modules.txt +++ b/test/prism/snapshots/modules.txt @@ -18,7 +18,8 @@ │ │ ├── name_loc: (1,9)-(1,10) = "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,11)-(1,12) = "=" │ ├── end_keyword_loc: (1,15)-(1,18) = "end" │ └── name: :A @@ -95,7 +96,8 @@ │ │ │ ├── name_loc: (9,1)-(9,2) = "x" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (9,5)-(9,6)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (9,3)-(9,4) = "=" │ │ ├── rescue_clause: │ │ │ @ RescueNode (location: (9,8)-(9,14)) @@ -168,7 +170,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (17,9)-(17,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (17,10)-(17,11) = "]" │ │ └── block: ∅ │ ├── child: diff --git a/test/prism/snapshots/next.txt b/test/prism/snapshots/next.txt index aa11809246f50a..64ec3ebc91a2c0 100644 --- a/test/prism/snapshots/next.txt +++ b/test/prism/snapshots/next.txt @@ -16,7 +16,8 @@ │ │ │ │ @ StatementsNode (location: (3,6)-(3,7)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── opening_loc: (3,5)-(3,6) = "(" │ │ │ └── closing_loc: (3,7)-(3,8) = ")" │ │ ├── @ ParenthesesNode (location: (3,10)-(3,13)) @@ -24,7 +25,8 @@ │ │ │ │ @ StatementsNode (location: (3,11)-(3,12)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,11)-(3,12)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: (3,10)-(3,11) = "(" │ │ │ └── closing_loc: (3,12)-(3,13) = ")" │ │ └── @ ParenthesesNode (location: (3,15)-(3,18)) @@ -32,7 +34,8 @@ │ │ │ @ StatementsNode (location: (3,16)-(3,17)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,16)-(3,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (3,15)-(3,16) = "(" │ │ └── closing_loc: (3,17)-(3,18) = ")" │ └── keyword_loc: (3,0)-(3,4) = "next" @@ -42,7 +45,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,5)-(5,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── keyword_loc: (5,0)-(5,4) = "next" ├── @ NextNode (location: (7,0)-(8,1)) │ ├── arguments: @@ -50,11 +54,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (7,5)-(7,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (7,8)-(7,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (8,0)-(8,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── keyword_loc: (7,0)-(7,4) = "next" ├── @ NextNode (location: (10,0)-(10,12)) │ ├── arguments: @@ -62,11 +69,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (10,5)-(10,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (10,8)-(10,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (10,11)-(10,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── keyword_loc: (10,0)-(10,4) = "next" ├── @ NextNode (location: (12,0)-(12,14)) │ ├── arguments: @@ -77,11 +87,14 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 3) │ │ │ ├── @ IntegerNode (location: (12,6)-(12,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (12,9)-(12,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (12,12)-(12,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (12,5)-(12,6) = "[" │ │ └── closing_loc: (12,13)-(12,14) = "]" │ └── keyword_loc: (12,0)-(12,4) = "next" @@ -95,9 +108,11 @@ │ │ │ @ StatementsNode (location: (15,2)-(16,3)) │ │ │ └── body: (length: 2) │ │ │ ├── @ IntegerNode (location: (15,2)-(15,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (14,4)-(14,5) = "(" │ │ └── closing_loc: (17,0)-(17,1) = ")" │ └── keyword_loc: (14,0)-(14,4) = "next" @@ -105,7 +120,8 @@ │ ├── arguments: ∅ │ └── keyword_loc: (19,0)-(19,4) = "next" ├── @ IntegerNode (location: (20,0)-(20,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ NextNode (location: (22,0)-(22,6)) │ ├── arguments: │ │ @ ArgumentsNode (location: (22,4)-(22,6)) @@ -126,7 +142,8 @@ │ │ @ StatementsNode (location: (24,5)-(24,6)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (24,5)-(24,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (24,4)-(24,5) = "(" │ └── closing_loc: (24,6)-(24,7) = ")" └── keyword_loc: (24,0)-(24,4) = "next" diff --git a/test/prism/snapshots/nils.txt b/test/prism/snapshots/nils.txt index cbadbcf911784f..f72745560fee7e 100644 --- a/test/prism/snapshots/nils.txt +++ b/test/prism/snapshots/nils.txt @@ -17,7 +17,8 @@ │ │ @ StatementsNode (location: (10,6)-(10,7)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (10,6)-(10,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_loc: (10,0)-(10,3) = "END" │ ├── opening_loc: (10,4)-(10,5) = "{" │ └── closing_loc: (10,8)-(10,9) = "}" @@ -26,7 +27,8 @@ │ @ StatementsNode (location: (12,8)-(12,9)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (12,8)-(12,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── keyword_loc: (12,0)-(12,5) = "BEGIN" ├── opening_loc: (12,6)-(12,7) = "{" └── closing_loc: (12,10)-(12,11) = "}" diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt index c27f2a63541c44..abcbf44c5e8058 100644 --- a/test/prism/snapshots/numbers.txt +++ b/test/prism/snapshots/numbers.txt @@ -4,58 +4,80 @@ @ StatementsNode (location: (1,0)-(67,5)) └── body: (length: 34) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── @ IntegerNode (location: (3,0)-(3,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ FloatNode (location: (5,0)-(5,3)) ├── @ IntegerNode (location: (7,0)-(7,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IntegerNode (location: (9,0)-(9,3)) - │ └── flags: binary + │ ├── flags: binary + │ └── value: 0 ├── @ IntegerNode (location: (11,0)-(11,3)) - │ └── flags: binary + │ ├── flags: binary + │ └── value: 1 ├── @ IntegerNode (location: (13,0)-(13,4)) - │ └── flags: binary + │ ├── flags: binary + │ └── value: 2 ├── @ IntegerNode (location: (15,0)-(15,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── @ IntegerNode (location: (17,0)-(17,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IntegerNode (location: (19,0)-(19,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IntegerNode (location: (21,0)-(21,2)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 0 ├── @ IntegerNode (location: (23,0)-(23,2)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 1 ├── @ IntegerNode (location: (25,0)-(25,2)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 2 ├── @ IntegerNode (location: (27,0)-(27,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 0 ├── @ IntegerNode (location: (29,0)-(29,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 1 ├── @ IntegerNode (location: (31,0)-(31,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 2 ├── @ IntegerNode (location: (33,0)-(33,3)) - │ └── flags: hexadecimal + │ ├── flags: hexadecimal + │ └── value: 0 ├── @ IntegerNode (location: (35,0)-(35,3)) - │ └── flags: hexadecimal + │ ├── flags: hexadecimal + │ └── value: 1 ├── @ IntegerNode (location: (37,0)-(37,3)) - │ └── flags: hexadecimal + │ ├── flags: hexadecimal + │ └── value: 2 ├── @ ImaginaryNode (location: (39,0)-(39,2)) │ └── numeric: │ @ IntegerNode (location: (39,0)-(39,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ RationalNode (location: (41,0)-(41,2)) │ └── numeric: │ @ IntegerNode (location: (41,0)-(41,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IntegerNode (location: (43,0)-(43,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -1 ├── @ ImaginaryNode (location: (45,0)-(45,3)) │ └── numeric: │ @ RationalNode (location: (45,0)-(45,2)) │ └── numeric: │ @ IntegerNode (location: (45,0)-(45,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ RationalNode (location: (47,0)-(47,4)) │ └── numeric: │ @ FloatNode (location: (47,0)-(47,3)) @@ -69,7 +91,8 @@ │ @ RationalNode (location: (51,0)-(51,3)) │ └── numeric: │ @ IntegerNode (location: (51,0)-(51,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -1 ├── @ RationalNode (location: (53,0)-(53,5)) │ └── numeric: │ @ FloatNode (location: (53,0)-(53,4)) @@ -81,28 +104,34 @@ ├── @ RationalNode (location: (57,0)-(57,4)) │ └── numeric: │ @ IntegerNode (location: (57,0)-(57,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 1 ├── @ ImaginaryNode (location: (59,0)-(59,4)) │ └── numeric: │ @ IntegerNode (location: (59,0)-(59,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 1 ├── @ ImaginaryNode (location: (61,0)-(61,5)) │ └── numeric: │ @ RationalNode (location: (61,0)-(61,4)) │ └── numeric: │ @ IntegerNode (location: (61,0)-(61,3)) - │ └── flags: octal + │ ├── flags: octal + │ └── value: 1 ├── @ RationalNode (location: (63,0)-(63,4)) │ └── numeric: │ @ IntegerNode (location: (63,0)-(63,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ImaginaryNode (location: (65,0)-(65,4)) │ └── numeric: │ @ IntegerNode (location: (65,0)-(65,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ ImaginaryNode (location: (67,0)-(67,5)) └── numeric: @ RationalNode (location: (67,0)-(67,4)) └── numeric: @ IntegerNode (location: (67,0)-(67,3)) - └── flags: binary + ├── flags: binary + └── value: 1 diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index ecb7ceb1cbf8b4..7080749a9e2924 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -34,7 +34,8 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (2,4)-(2,6) = "=>" ├── @ MatchRequiredNode (location: (3,0)-(3,10)) │ ├── value: @@ -67,7 +68,8 @@ │ │ @ ImaginaryNode (location: (4,7)-(4,9)) │ │ └── numeric: │ │ @ IntegerNode (location: (4,7)-(4,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (4,4)-(4,6) = "=>" ├── @ MatchRequiredNode (location: (5,0)-(5,9)) │ ├── value: @@ -85,7 +87,8 @@ │ │ @ RationalNode (location: (5,7)-(5,9)) │ │ └── numeric: │ │ @ IntegerNode (location: (5,7)-(5,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (5,4)-(5,6) = "=>" ├── @ MatchRequiredNode (location: (6,0)-(6,11)) │ ├── value: @@ -516,10 +519,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (28,7)-(28,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ IntegerNode (location: (28,12)-(28,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (28,9)-(28,11) = ".." │ └── operator_loc: (28,4)-(28,6) = "=>" ├── @ MatchRequiredNode (location: (29,0)-(29,17)) @@ -562,12 +567,14 @@ │ │ │ @ ImaginaryNode (location: (30,7)-(30,9)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (30,7)-(30,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ ImaginaryNode (location: (30,13)-(30,15)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (30,13)-(30,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (30,10)-(30,12) = ".." │ └── operator_loc: (30,4)-(30,6) = "=>" ├── @ MatchRequiredNode (location: (31,0)-(31,15)) @@ -589,12 +596,14 @@ │ │ │ @ RationalNode (location: (31,7)-(31,9)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (31,7)-(31,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: │ │ │ @ RationalNode (location: (31,13)-(31,15)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (31,13)-(31,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (31,10)-(31,12) = ".." │ └── operator_loc: (31,4)-(31,6) = "=>" ├── @ MatchRequiredNode (location: (32,0)-(32,19)) @@ -1238,7 +1247,8 @@ │ ├── name_loc: (54,0)-(54,3) = "bar" │ ├── value: │ │ @ IntegerNode (location: (54,6)-(54,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (54,4)-(54,5) = "=" ├── @ MatchRequiredNode (location: (54,9)-(54,20)) │ ├── value: @@ -1333,7 +1343,8 @@ │ │ @ PinnedExpressionNode (location: (59,7)-(59,11)) │ │ ├── expression: │ │ │ @ IntegerNode (location: (59,9)-(59,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── operator_loc: (59,7)-(59,8) = "^" │ │ ├── lparen_loc: (59,8)-(59,9) = "(" │ │ └── rparen_loc: (59,10)-(59,11) = ")" @@ -1540,7 +1551,8 @@ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (69,11)-(69,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── opening_loc: (69,10)-(69,11) = "(" @@ -1565,11 +1577,14 @@ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 3) │ │ │ ├── @ IntegerNode (location: (70,11)-(70,12)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (70,14)-(70,15)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (70,17)-(70,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── opening_loc: (70,10)-(70,11) = "(" @@ -1745,7 +1760,8 @@ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (77,11)-(77,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── opening_loc: (77,10)-(77,11) = "[" @@ -1770,11 +1786,14 @@ │ │ │ └── name: :Foo │ │ ├── requireds: (length: 3) │ │ │ ├── @ IntegerNode (location: (78,11)-(78,12)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── @ IntegerNode (location: (78,14)-(78,15)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (78,17)-(78,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── opening_loc: (78,10)-(78,11) = "[" @@ -2390,7 +2409,8 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ IntegerNode (location: (105,7)-(105,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (105,4)-(105,6) = "in" ├── @ MatchPredicateNode (location: (106,0)-(106,10)) │ ├── value: @@ -2423,7 +2443,8 @@ │ │ @ ImaginaryNode (location: (107,7)-(107,9)) │ │ └── numeric: │ │ @ IntegerNode (location: (107,7)-(107,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (107,4)-(107,6) = "in" ├── @ MatchPredicateNode (location: (108,0)-(108,9)) │ ├── value: @@ -2441,7 +2462,8 @@ │ │ @ RationalNode (location: (108,7)-(108,9)) │ │ └── numeric: │ │ @ IntegerNode (location: (108,7)-(108,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (108,4)-(108,6) = "in" ├── @ MatchPredicateNode (location: (109,0)-(109,11)) │ ├── value: @@ -2920,7 +2942,8 @@ │ │ └── @ InNode (location: (136,10)-(136,19)) │ │ ├── pattern: │ │ │ @ IntegerNode (location: (136,13)-(136,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── statements: ∅ │ │ ├── in_loc: (136,10)-(136,12) = "in" │ │ └── then_loc: (136,15)-(136,19) = "then" @@ -2967,7 +2990,8 @@ │ │ │ @ ImaginaryNode (location: (138,13)-(138,15)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (138,13)-(138,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── statements: ∅ │ │ ├── in_loc: (138,10)-(138,12) = "in" │ │ └── then_loc: (138,16)-(138,20) = "then" @@ -2992,7 +3016,8 @@ │ │ │ @ RationalNode (location: (139,13)-(139,15)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (139,13)-(139,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── statements: ∅ │ │ ├── in_loc: (139,10)-(139,12) = "in" │ │ └── then_loc: (139,16)-(139,20) = "then" @@ -3620,7 +3645,8 @@ │ │ │ │ @ StatementsNode (location: (163,13)-(163,14)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (163,13)-(163,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── consequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ @@ -3691,7 +3717,8 @@ │ │ │ │ └── @ ImaginaryNode (location: (165,13)-(165,15)) │ │ │ │ └── numeric: │ │ │ │ @ IntegerNode (location: (165,13)-(165,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── consequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ @@ -3728,7 +3755,8 @@ │ │ │ │ └── @ RationalNode (location: (166,13)-(166,15)) │ │ │ │ └── numeric: │ │ │ │ @ IntegerNode (location: (166,13)-(166,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── consequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ @@ -4722,9 +4750,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (205,16)-(205,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (205,19)-(205,20)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ CallNode (location: (206,0)-(208,3)) @@ -4749,9 +4779,11 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (207,3)-(207,4)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (207,6)-(207,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── opening_loc: (207,2)-(207,3) = "[" │ │ │ └── closing_loc: (207,7)-(207,8) = "]" │ │ ├── pattern: @@ -4819,7 +4851,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (212,0)-(212,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: (212,1)-(212,2) = "." │ ├── name: :then │ ├── message_loc: (212,2)-(212,6) = "then" @@ -4838,7 +4871,8 @@ │ │ └── @ MatchPredicateNode (location: (212,9)-(212,17)) │ │ ├── value: │ │ │ @ IntegerNode (location: (212,9)-(212,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── pattern: │ │ │ @ PinnedVariableNode (location: (212,14)-(212,17)) │ │ │ ├── variable: diff --git a/test/prism/snapshots/procs.txt b/test/prism/snapshots/procs.txt index 2cc30618a0ab2f..1329ae6a5f210e 100644 --- a/test/prism/snapshots/procs.txt +++ b/test/prism/snapshots/procs.txt @@ -146,7 +146,8 @@ │ │ │ │ ├── operator_loc: (17,8)-(17,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (17,10)-(17,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 2) @@ -195,7 +196,8 @@ │ │ │ │ ├── operator_loc: (19,9)-(19,10) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (19,11)-(19,12)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (19,14)-(19,16)) │ │ │ │ ├── flags: ∅ @@ -254,7 +256,8 @@ │ │ │ │ ├── operator_loc: (21,9)-(21,10) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (21,11)-(21,12)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (21,14)-(21,16)) │ │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/range_begin_open_exclusive.txt b/test/prism/snapshots/range_begin_open_exclusive.txt index 0ac4d10bf76c23..a630b01ef19d05 100644 --- a/test/prism/snapshots/range_begin_open_exclusive.txt +++ b/test/prism/snapshots/range_begin_open_exclusive.txt @@ -8,5 +8,6 @@ ├── left: ∅ ├── right: │ @ IntegerNode (location: (1,3)-(1,4)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,0)-(1,3) = "..." diff --git a/test/prism/snapshots/range_begin_open_inclusive.txt b/test/prism/snapshots/range_begin_open_inclusive.txt index 1cba8942211aa3..dc8ef0d2dbc00b 100644 --- a/test/prism/snapshots/range_begin_open_inclusive.txt +++ b/test/prism/snapshots/range_begin_open_inclusive.txt @@ -8,5 +8,6 @@ ├── left: ∅ ├── right: │ @ IntegerNode (location: (1,2)-(1,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,0)-(1,2) = ".." diff --git a/test/prism/snapshots/range_end_open_exclusive.txt b/test/prism/snapshots/range_end_open_exclusive.txt index 76b8eb197ecde1..17a75f89456fe8 100644 --- a/test/prism/snapshots/range_end_open_exclusive.txt +++ b/test/prism/snapshots/range_end_open_exclusive.txt @@ -7,6 +7,7 @@ ├── flags: exclude_end ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── right: ∅ └── operator_loc: (1,1)-(1,4) = "..." diff --git a/test/prism/snapshots/range_end_open_inclusive.txt b/test/prism/snapshots/range_end_open_inclusive.txt index 576ea40fa54fb8..b49272d8cd1eba 100644 --- a/test/prism/snapshots/range_end_open_inclusive.txt +++ b/test/prism/snapshots/range_end_open_inclusive.txt @@ -7,6 +7,7 @@ ├── flags: ∅ ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── right: ∅ └── operator_loc: (1,1)-(1,3) = ".." diff --git a/test/prism/snapshots/ranges.txt b/test/prism/snapshots/ranges.txt index 906bf2de6bbe1d..2fffe805376040 100644 --- a/test/prism/snapshots/ranges.txt +++ b/test/prism/snapshots/ranges.txt @@ -12,7 +12,8 @@ │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (1,1)-(1,4) = "..." │ ├── opening_loc: (1,0)-(1,1) = "(" │ └── closing_loc: (1,5)-(1,6) = ")" @@ -25,7 +26,8 @@ │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (3,3)-(3,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (3,1)-(3,3) = ".." │ ├── opening_loc: (3,0)-(3,1) = "(" │ └── closing_loc: (3,4)-(3,5) = ")" @@ -33,10 +35,12 @@ │ ├── flags: exclude_end │ ├── left: │ │ @ IntegerNode (location: (5,0)-(5,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (5,4)-(5,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (5,1)-(5,4) = "..." ├── @ CallNode (location: (7,0)-(7,9)) │ ├── flags: ∅ @@ -64,7 +68,8 @@ │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (7,7)-(7,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (7,4)-(7,7) = "..." │ ├── closing_loc: (7,8)-(7,9) = "]" │ └── block: ∅ @@ -105,7 +110,8 @@ │ │ ├── flags: exclude_end │ │ ├── left: │ │ │ @ IntegerNode (location: (11,1)-(11,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (11,2)-(11,5) = "..." │ ├── opening_loc: (11,0)-(11,1) = "(" @@ -114,10 +120,12 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (13,0)-(13,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (13,3)-(13,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (13,1)-(13,3) = ".." ├── @ HashNode (location: (15,0)-(15,14)) │ ├── opening_loc: (15,0)-(15,1) = "{" @@ -156,7 +164,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (17,1)-(17,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (17,2)-(17,4) = ".." │ ├── opening_loc: (17,0)-(17,1) = "(" @@ -165,14 +174,16 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (19,0)-(19,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ RangeNode (location: (19,5)-(19,8)) │ │ ├── flags: ∅ │ │ ├── left: ∅ │ │ ├── right: │ │ │ @ IntegerNode (location: (19,7)-(19,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (19,5)-(19,7) = ".." │ └── operator_loc: (19,2)-(19,4) = ".." ├── @ AndNode (location: (21,0)-(21,8)) @@ -181,12 +192,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (21,0)-(21,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (21,1)-(21,3) = ".." │ ├── right: │ │ @ IntegerNode (location: (21,7)-(21,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (21,4)-(21,6) = "&&" ├── @ CallNode (location: (23,0)-(23,8)) │ ├── flags: ∅ @@ -195,7 +208,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (23,0)-(23,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (23,1)-(23,3) = ".." │ ├── call_operator_loc: ∅ @@ -207,7 +221,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,7)-(23,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,8)) @@ -217,7 +232,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (25,0)-(25,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (25,1)-(25,3) = ".." │ ├── call_operator_loc: ∅ @@ -229,7 +245,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (25,7)-(25,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (27,0)-(27,9)) @@ -239,7 +256,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (27,0)-(27,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (27,1)-(27,3) = ".." │ ├── call_operator_loc: ∅ @@ -251,7 +269,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,8)-(27,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,9)) @@ -261,7 +280,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (29,0)-(29,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (29,1)-(29,3) = ".." │ ├── call_operator_loc: ∅ @@ -273,7 +293,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,8)-(29,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,8)) @@ -283,7 +304,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (31,0)-(31,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (31,1)-(31,3) = ".." │ ├── call_operator_loc: ∅ @@ -295,7 +317,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,7)-(31,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,8)) @@ -305,7 +328,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (33,0)-(33,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (33,1)-(33,3) = ".." │ ├── call_operator_loc: ∅ @@ -317,7 +341,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,7)-(33,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,7)) @@ -327,7 +352,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (35,0)-(35,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (35,1)-(35,3) = ".." │ ├── call_operator_loc: ∅ @@ -339,7 +365,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,6)-(35,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,7)) @@ -349,7 +376,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (37,0)-(37,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (37,1)-(37,3) = ".." │ ├── call_operator_loc: ∅ @@ -361,7 +389,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (37,6)-(37,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,8)) @@ -371,7 +400,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (39,0)-(39,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (39,1)-(39,3) = ".." │ ├── call_operator_loc: ∅ @@ -383,7 +413,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (39,7)-(39,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (41,0)-(41,8)) @@ -393,7 +424,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (41,0)-(41,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (41,1)-(41,3) = ".." │ ├── call_operator_loc: ∅ @@ -405,7 +437,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (41,7)-(41,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (43,0)-(43,8)) @@ -415,7 +448,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (43,0)-(43,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (43,1)-(43,3) = ".." │ ├── call_operator_loc: ∅ @@ -427,7 +461,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (43,7)-(43,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (45,0)-(45,8)) @@ -437,7 +472,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (45,0)-(45,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (45,1)-(45,3) = ".." │ ├── call_operator_loc: ∅ @@ -449,20 +485,23 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (45,7)-(45,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ RangeNode (location: (47,0)-(47,7)) │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (47,0)-(47,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ CallNode (location: (47,4)-(47,7)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (47,6)-(47,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :+@ │ │ ├── message_loc: (47,4)-(47,5) = "+" @@ -475,13 +514,15 @@ ├── flags: ∅ ├── left: │ @ IntegerNode (location: (49,0)-(49,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── right: │ @ CallNode (location: (49,4)-(49,7)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (49,6)-(49,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── call_operator_loc: ∅ │ ├── name: :-@ │ ├── message_loc: (49,4)-(49,5) = "-" diff --git a/test/prism/snapshots/regex.txt b/test/prism/snapshots/regex.txt index 82cb489c4c1e37..8f3e2595168b86 100644 --- a/test/prism/snapshots/regex.txt +++ b/test/prism/snapshots/regex.txt @@ -313,7 +313,8 @@ │ ├── name_loc: (39,0)-(39,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (39,4)-(39,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (39,2)-(39,3) = "=" └── @ CallNode (location: (40,0)-(40,24)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/repeat_parameters.txt b/test/prism/snapshots/repeat_parameters.txt index 031a304eb03f60..fd98294ce6150e 100644 --- a/test/prism/snapshots/repeat_parameters.txt +++ b/test/prism/snapshots/repeat_parameters.txt @@ -294,7 +294,8 @@ │ │ │ │ ├── operator_loc: (22,11)-(22,12) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (22,13)-(22,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (22,16)-(22,22)) │ │ │ ├── flags: repeated_parameter │ │ │ ├── name: :_a @@ -302,7 +303,8 @@ │ │ │ ├── operator_loc: (22,19)-(22,20) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (22,21)-(22,22)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -362,14 +364,16 @@ │ │ │ │ ├── name_loc: (28,8)-(28,11) = "_a:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (28,12)-(28,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ OptionalKeywordParameterNode (location: (28,15)-(28,20)) │ │ │ ├── flags: repeated_parameter │ │ │ ├── name: :_a │ │ │ ├── name_loc: (28,15)-(28,18) = "_a:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (28,19)-(28,20)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ diff --git a/test/prism/snapshots/rescue.txt b/test/prism/snapshots/rescue.txt index fab9a8f70d486c..d987c49617384c 100644 --- a/test/prism/snapshots/rescue.txt +++ b/test/prism/snapshots/rescue.txt @@ -76,7 +76,8 @@ │ │ @ NilNode (location: (12,11)-(12,14)) │ ├── right: │ │ @ IntegerNode (location: (12,18)-(12,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (12,15)-(12,17) = "||" ├── @ RescueModifierNode (location: (14,0)-(14,22)) │ ├── expression: @@ -101,7 +102,8 @@ │ │ @ StatementsNode (location: (14,17)-(14,18)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (14,17)-(14,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: │ │ @ ElseNode (location: (14,19)-(14,22)) │ │ ├── else_keyword_loc: (14,19)-(14,20) = ":" @@ -109,7 +111,8 @@ │ │ │ @ StatementsNode (location: (14,21)-(14,22)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (14,21)-(14,22)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ BeginNode (location: (16,0)-(16,24)) @@ -306,7 +309,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (26,31)-(26,33)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── keyword_loc: (26,34)-(26,40) = "rescue" diff --git a/test/prism/snapshots/return.txt b/test/prism/snapshots/return.txt index 647ae1af9d4067..9a33076193cb0d 100644 --- a/test/prism/snapshots/return.txt +++ b/test/prism/snapshots/return.txt @@ -17,7 +17,8 @@ │ │ │ @ StatementsNode (location: (3,8)-(3,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,8)-(3,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (3,7)-(3,8) = "(" │ │ └── closing_loc: (3,9)-(3,10) = ")" │ ├── @ ParenthesesNode (location: (3,12)-(3,15)) @@ -25,7 +26,8 @@ │ │ │ @ StatementsNode (location: (3,13)-(3,14)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,13)-(3,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (3,12)-(3,13) = "(" │ │ └── closing_loc: (3,14)-(3,15) = ")" │ └── @ ParenthesesNode (location: (3,17)-(3,20)) @@ -33,7 +35,8 @@ │ │ @ StatementsNode (location: (3,18)-(3,19)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (3,18)-(3,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── opening_loc: (3,17)-(3,18) = "(" │ └── closing_loc: (3,19)-(3,20) = ")" ├── @ ReturnNode (location: (5,0)-(5,9)) @@ -46,7 +49,8 @@ │ ├── operator_loc: (5,7)-(5,8) = "*" │ └── expression: │ @ IntegerNode (location: (5,8)-(5,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ReturnNode (location: (7,0)-(7,8)) │ ├── keyword_loc: (7,0)-(7,6) = "return" │ └── arguments: @@ -54,7 +58,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (7,7)-(7,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ReturnNode (location: (9,0)-(10,1)) │ ├── keyword_loc: (9,0)-(9,6) = "return" │ └── arguments: @@ -62,11 +67,14 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (9,7)-(9,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (9,10)-(9,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (10,0)-(10,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── @ ReturnNode (location: (12,0)-(12,14)) │ ├── keyword_loc: (12,0)-(12,6) = "return" │ └── arguments: @@ -74,11 +82,14 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (12,7)-(12,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (12,10)-(12,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (12,13)-(12,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── @ ReturnNode (location: (14,0)-(14,16)) │ ├── keyword_loc: (14,0)-(14,6) = "return" │ └── arguments: @@ -89,11 +100,14 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (14,8)-(14,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (14,11)-(14,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (14,14)-(14,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── opening_loc: (14,7)-(14,8) = "[" │ └── closing_loc: (14,15)-(14,16) = "]" ├── @ ReturnNode (location: (16,0)-(19,1)) @@ -107,9 +121,11 @@ │ │ @ StatementsNode (location: (17,2)-(18,3)) │ │ └── body: (length: 2) │ │ ├── @ IntegerNode (location: (17,2)-(17,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (18,2)-(18,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (16,6)-(16,7) = "(" │ └── closing_loc: (19,0)-(19,1) = ")" ├── @ ReturnNode (location: (21,0)-(21,8)) @@ -133,6 +149,7 @@ │ @ StatementsNode (location: (23,7)-(23,8)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (23,7)-(23,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── opening_loc: (23,6)-(23,7) = "(" └── closing_loc: (23,8)-(23,9) = ")" diff --git a/test/prism/snapshots/seattlerb/BEGIN.txt b/test/prism/snapshots/seattlerb/BEGIN.txt index 3595e2a05c82a9..246f39cbba87d9 100644 --- a/test/prism/snapshots/seattlerb/BEGIN.txt +++ b/test/prism/snapshots/seattlerb/BEGIN.txt @@ -8,7 +8,8 @@ │ @ StatementsNode (location: (1,8)-(1,10)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── keyword_loc: (1,0)-(1,5) = "BEGIN" ├── opening_loc: (1,6)-(1,7) = "{" └── closing_loc: (1,11)-(1,12) = "}" diff --git a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt index f90f073d721ae9..4a2a48b794bfde 100644 --- a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt +++ b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt @@ -203,7 +203,8 @@ │ │ │ ├── name_loc: (61,4)-(61,5) = "Z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (61,8)-(61,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── operator_loc: (61,6)-(61,7) = "=" │ │ ├── end_keyword_loc: (62,2)-(62,5) = "end" │ │ └── name: :Y @@ -326,7 +327,8 @@ │ │ │ ├── name_loc: (84,4)-(84,5) = "Z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (84,8)-(84,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── operator_loc: (84,6)-(84,7) = "=" │ │ ├── end_keyword_loc: (85,2)-(85,5) = "end" │ │ └── name: :Y diff --git a/test/prism/snapshots/seattlerb/aref_args_assocs.txt b/test/prism/snapshots/seattlerb/aref_args_assocs.txt index 398a014248c610..b729186dc5e3d4 100644 --- a/test/prism/snapshots/seattlerb/aref_args_assocs.txt +++ b/test/prism/snapshots/seattlerb/aref_args_assocs.txt @@ -12,10 +12,12 @@ │ └── @ AssocNode (location: (1,1)-(1,7)) │ ├── key: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── value: │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── opening_loc: (1,0)-(1,1) = "[" └── closing_loc: (1,7)-(1,8) = "]" diff --git a/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt b/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt index 7a63842f366898..0e9454d780b22a 100644 --- a/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt +++ b/test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt @@ -7,17 +7,20 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,4)-(1,10)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,4)-(1,10)) │ ├── key: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── opening_loc: (1,0)-(1,1) = "[" └── closing_loc: (1,10)-(1,11) = "]" diff --git a/test/prism/snapshots/seattlerb/args_kw_block.txt b/test/prism/snapshots/seattlerb/args_kw_block.txt index b0f8fa8fd7917c..1ad933c74e3f4e 100644 --- a/test/prism/snapshots/seattlerb/args_kw_block.txt +++ b/test/prism/snapshots/seattlerb/args_kw_block.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (1,12)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/array_line_breaks.txt b/test/prism/snapshots/seattlerb/array_line_breaks.txt index a08ee030527baa..880fedf93308b5 100644 --- a/test/prism/snapshots/seattlerb/array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/array_line_breaks.txt @@ -21,4 +21,5 @@ │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (3,3)-(3,4) = "]" └── @ IntegerNode (location: (4,0)-(4,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/assoc_label.txt b/test/prism/snapshots/seattlerb/assoc_label.txt index 725a74f9114852..923f5450f431ce 100644 --- a/test/prism/snapshots/seattlerb/assoc_label.txt +++ b/test/prism/snapshots/seattlerb/assoc_label.txt @@ -27,7 +27,8 @@ │ │ └── unescaped: "b" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: ∅ ├── closing_loc: (1,5)-(1,6) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt b/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt index c869af46072bb0..589433eda89916 100644 --- a/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt +++ b/test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt @@ -17,6 +17,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt b/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt index 2c14d9566cb8a3..9b04ae9656ed86 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_array_arg.txt @@ -28,12 +28,15 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (1,2)-(1,3) = "[" │ │ └── closing_loc: (1,7)-(1,8) = "]" │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt b/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt index 2d8f509a501de7..39544e98da2c3f 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt @@ -10,13 +10,17 @@ │ ├── flags: ∅ │ ├── elements: (length: 4) │ │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (1,11)-(1,12) = "]" ├── call_operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt b/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt index 5aec9c5c6f2d56..d4c4fe107059c9 100644 --- a/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt +++ b/test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bang_eq.txt b/test/prism/snapshots/seattlerb/bang_eq.txt index 553362030e4c1c..ec3dd888b27ef8 100644 --- a/test/prism/snapshots/seattlerb/bang_eq.txt +++ b/test/prism/snapshots/seattlerb/bang_eq.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :!= ├── message_loc: (1,2)-(1,4) = "!=" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/bdot2.txt b/test/prism/snapshots/seattlerb/bdot2.txt index 6bb76603c38cd9..d4fb86fbe66f65 100644 --- a/test/prism/snapshots/seattlerb/bdot2.txt +++ b/test/prism/snapshots/seattlerb/bdot2.txt @@ -8,7 +8,8 @@ │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (1,2)-(1,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator_loc: (1,0)-(1,2) = ".." ├── @ RangeNode (location: (2,2)-(2,5)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bdot3.txt b/test/prism/snapshots/seattlerb/bdot3.txt index 27b87b1867e349..0c960f045870a0 100644 --- a/test/prism/snapshots/seattlerb/bdot3.txt +++ b/test/prism/snapshots/seattlerb/bdot3.txt @@ -8,7 +8,8 @@ │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (1,3)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator_loc: (1,0)-(1,3) = "..." ├── @ RangeNode (location: (2,2)-(2,6)) │ ├── flags: exclude_end diff --git a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt index 686fa100f1b48d..6603e5c8945548 100644 --- a/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt +++ b/test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt @@ -9,7 +9,8 @@ │ @ StatementsNode (location: (2,2)-(2,3)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (2,2)-(2,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── rescue_clause: │ @ RescueNode (location: (3,0)-(4,3)) │ ├── keyword_loc: (3,0)-(3,6) = "rescue" @@ -20,7 +21,8 @@ │ │ @ StatementsNode (location: (4,2)-(4,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (4,2)-(4,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── consequent: ∅ ├── else_clause: │ @ ElseNode (location: (5,0)-(7,6)) @@ -29,7 +31,8 @@ │ │ @ StatementsNode (location: (6,2)-(6,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (6,2)-(6,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── end_keyword_loc: (7,0)-(7,6) = "ensure" ├── ensure_clause: │ @ EnsureNode (location: (7,0)-(9,3)) @@ -38,6 +41,7 @@ │ │ @ StatementsNode (location: (8,2)-(8,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,2)-(8,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ └── end_keyword_loc: (9,0)-(9,3) = "end" └── end_keyword_loc: (9,0)-(9,3) = "end" diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt index 8916d7b9d125c2..ee9644d59d8bbc 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt index 3167d249bdc88d..799bd21057aad4 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,15)-(1,17)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt index b82f363dc24f6c..b5df136a622987 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_arg_optional.txt b/test/prism/snapshots/seattlerb/block_arg_optional.txt index fe5c06ab7de467..8a850e9a21a1e1 100644 --- a/test/prism/snapshots/seattlerb/block_arg_optional.txt +++ b/test/prism/snapshots/seattlerb/block_arg_optional.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_args_opt1.txt b/test/prism/snapshots/seattlerb/block_args_opt1.txt index 4c06f829549bdf..1f21c0a4773b8c 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt1.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt1.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_args_opt2.txt b/test/prism/snapshots/seattlerb/block_args_opt2.txt index a7fb2d50a6f73a..a8d736dde73c94 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2.txt @@ -28,7 +28,8 @@ │ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ OptionalParameterNode (location: (1,11)-(1,14)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :c @@ -36,7 +37,8 @@ │ │ │ ├── operator_loc: (1,12)-(1,13) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt index 26cfc328870410..0403851ed7b7ea 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt @@ -31,7 +31,8 @@ │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :c @@ -39,7 +40,8 @@ │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,20)-(1,22)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 24 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_args_opt3.txt b/test/prism/snapshots/seattlerb/block_args_opt3.txt index 2eb98c3c903154..ff4495019c7cea 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt3.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt3.txt @@ -31,7 +31,8 @@ │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :c @@ -39,7 +40,8 @@ │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,20)-(1,22)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 24 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_kw.txt b/test/prism/snapshots/seattlerb/block_kw.txt index 36db338271c7bd..f022637dae6dea 100644 --- a/test/prism/snapshots/seattlerb/block_kw.txt +++ b/test/prism/snapshots/seattlerb/block_kw.txt @@ -30,7 +30,8 @@ │ │ │ ├── name_loc: (1,8)-(1,10) = "k:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── locals: (length: 0) diff --git a/test/prism/snapshots/seattlerb/block_opt_arg.txt b/test/prism/snapshots/seattlerb/block_opt_arg.txt index 2e53540491a52a..64dc928f14b326 100644 --- a/test/prism/snapshots/seattlerb/block_opt_arg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_arg.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,10)-(1,11)) diff --git a/test/prism/snapshots/seattlerb/block_opt_splat.txt b/test/prism/snapshots/seattlerb/block_opt_splat.txt index c15380150cbb1b..c18df9c27d41ff 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,12)-(1,14)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt index da383a3c887afc..3806809d2bd072 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,10)-(1,12)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/bug202.txt b/test/prism/snapshots/seattlerb/bug202.txt index 3faff193dcf078..377b53727ed67e 100644 --- a/test/prism/snapshots/seattlerb/bug202.txt +++ b/test/prism/snapshots/seattlerb/bug202.txt @@ -8,7 +8,8 @@ │ ├── name_loc: (1,0)-(1,7) = "$测试" │ ├── value: │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,8)-(1,9) = "=" └── @ LocalVariableWriteNode (location: (2,0)-(2,10)) ├── name: :测试 @@ -16,5 +17,6 @@ ├── name_loc: (2,0)-(2,6) = "测试" ├── value: │ @ IntegerNode (location: (2,9)-(2,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── operator_loc: (2,7)-(2,8) = "=" diff --git a/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt b/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt index 8c6472187094e5..53d6f9220b2c0d 100644 --- a/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt +++ b/test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt @@ -27,11 +27,13 @@ │ │ │ │ │ @ StatementsNode (location: (2,12)-(2,13)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (2,12)-(2,13)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (2,10)-(2,11) = "(" │ │ │ │ └── closing_loc: (2,13)-(2,14) = ")" │ │ │ └── @ IntegerNode (location: (2,16)-(2,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [] @@ -65,11 +67,13 @@ │ │ │ │ │ @ StatementsNode (location: (7,11)-(7,12)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── opening_loc: (7,10)-(7,11) = "(" │ │ │ │ └── closing_loc: (7,12)-(7,13) = ")" │ │ │ └── @ IntegerNode (location: (7,15)-(7,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [] @@ -95,10 +99,12 @@ │ │ │ @ StatementsNode (location: (11,4)-(11,5)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (11,2)-(11,3) = "(" │ │ └── closing_loc: (11,5)-(11,6) = ")" │ └── @ IntegerNode (location: (11,8)-(11,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_and.txt b/test/prism/snapshots/seattlerb/call_and.txt index 8c6bf2f2e34dc0..d3e88b3f9e418c 100644 --- a/test/prism/snapshots/seattlerb/call_and.txt +++ b/test/prism/snapshots/seattlerb/call_and.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :& ├── message_loc: (1,2)-(1,3) = "&" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_arg_assoc.txt b/test/prism/snapshots/seattlerb/call_arg_assoc.txt index f547c2183eddb8..27c19fd339243b 100644 --- a/test/prism/snapshots/seattlerb/call_arg_assoc.txt +++ b/test/prism/snapshots/seattlerb/call_arg_assoc.txt @@ -15,17 +15,20 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,9)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,5)-(1,9)) │ ├── key: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── closing_loc: (1,9)-(1,10) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt index a16c652ae4245a..0193eb1dfcf170 100644 --- a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt @@ -15,7 +15,8 @@ │ ├── flags: contains_keyword_splat │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,15)) │ ├── flags: ∅ │ └── elements: (length: 2) @@ -29,12 +30,14 @@ │ │ │ └── unescaped: "kw" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocSplatNode (location: (1,12)-(1,15)) │ ├── value: │ │ @ IntegerNode (location: (1,14)-(1,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,12)-(1,14) = "**" ├── closing_loc: (1,15)-(1,16) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt b/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt index ecb8157723424a..91c7725525f2ee 100644 --- a/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_arg_kwsplat.txt @@ -30,7 +30,8 @@ │ └── @ AssocSplatNode (location: (1,5)-(1,8)) │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,5)-(1,7) = "**" ├── closing_loc: (1,8)-(1,9) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt index cb048dba8f70a0..2d6f81c8186ff3 100644 --- a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt +++ b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt @@ -41,7 +41,8 @@ │ │ │ └── closing_loc: (1,7)-(1,9) = "\":" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ @@ -69,7 +70,8 @@ │ │ │ └── unescaped: "k" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,6)-(3,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ @@ -97,7 +99,8 @@ │ │ └── unescaped: "k" │ ├── value: │ │ @ IntegerNode (location: (5,6)-(5,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ └── operator_loc: ∅ ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt index 0cd275ee71b353..312a1981a06140 100644 --- a/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt @@ -15,17 +15,20 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,5)-(1,9)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (1,5)-(1,9)) │ ├── key: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,6)-(1,8) = "=>" ├── closing_loc: (1,10)-(1,11) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_args_command.txt b/test/prism/snapshots/seattlerb/call_args_command.txt index a8ef0c14db4389..f4a55ff58c36db 100644 --- a/test/prism/snapshots/seattlerb/call_args_command.txt +++ b/test/prism/snapshots/seattlerb/call_args_command.txt @@ -46,7 +46,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_arg.txt b/test/prism/snapshots/seattlerb/call_array_arg.txt index 3558ad0f0b98f1..95d2f4859d00ee 100644 --- a/test/prism/snapshots/seattlerb/call_array_arg.txt +++ b/test/prism/snapshots/seattlerb/call_array_arg.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :== ├── message_loc: (1,2)-(1,4) = "==" diff --git a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt index e1bd056fd4c8e3..091e21c00a6347 100644 --- a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt +++ b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt @@ -36,7 +36,8 @@ │ │ │ └── unescaped: "c" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,10)-(1,12) = "=>" │ ├── opening_loc: (1,2)-(1,3) = "[" │ └── closing_loc: (1,14)-(1,15) = "]" diff --git a/test/prism/snapshots/seattlerb/call_assoc.txt b/test/prism/snapshots/seattlerb/call_assoc.txt index 58ef23e7ec541e..438c2565538fe4 100644 --- a/test/prism/snapshots/seattlerb/call_assoc.txt +++ b/test/prism/snapshots/seattlerb/call_assoc.txt @@ -20,10 +20,12 @@ │ └── @ AssocNode (location: (1,2)-(1,6)) │ ├── key: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── closing_loc: (1,6)-(1,7) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_assoc_new.txt b/test/prism/snapshots/seattlerb/call_assoc_new.txt index bd31becacabd58..b4d7e0bf834d8b 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new.txt @@ -27,7 +27,8 @@ │ │ └── unescaped: "a" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: ∅ ├── closing_loc: (1,5)-(1,6) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt index 6f2b1fa876bc34..9587e2e074d292 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt @@ -40,7 +40,8 @@ │ │ │ @ StatementsNode (location: (2,0)-(2,1)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (2,0)-(2,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── consequent: │ │ │ @ ElseNode (location: (3,0)-(5,3)) │ │ │ ├── else_keyword_loc: (3,0)-(3,4) = "else" @@ -48,7 +49,8 @@ │ │ │ │ @ StatementsNode (location: (4,0)-(4,1)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (4,0)-(4,1)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" │ │ └── end_keyword_loc: (5,0)-(5,3) = "end" │ └── operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt index dbc5d9095a00fe..8d0b285172c4ce 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt @@ -20,10 +20,12 @@ │ └── @ AssocNode (location: (1,2)-(1,6)) │ ├── key: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── closing_loc: (1,7)-(1,8) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_bang_command_call.txt b/test/prism/snapshots/seattlerb/call_bang_command_call.txt index 2dca64ab31232d..5e4e10d953c798 100644 --- a/test/prism/snapshots/seattlerb/call_bang_command_call.txt +++ b/test/prism/snapshots/seattlerb/call_bang_command_call.txt @@ -28,7 +28,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── call_operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_bang_squiggle.txt b/test/prism/snapshots/seattlerb/call_bang_squiggle.txt index ba7dcfa262538e..bf11bc0136ff73 100644 --- a/test/prism/snapshots/seattlerb/call_bang_squiggle.txt +++ b/test/prism/snapshots/seattlerb/call_bang_squiggle.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :!~ ├── message_loc: (1,2)-(1,4) = "!~" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_carat.txt b/test/prism/snapshots/seattlerb/call_carat.txt index 7c0fdbc7bc1423..856e9a7847f8f6 100644 --- a/test/prism/snapshots/seattlerb/call_carat.txt +++ b/test/prism/snapshots/seattlerb/call_carat.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :^ ├── message_loc: (1,2)-(1,3) = "^" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_colon_parens.txt b/test/prism/snapshots/seattlerb/call_colon_parens.txt index 5522d7b39d39bc..6d10171a2b19c9 100644 --- a/test/prism/snapshots/seattlerb/call_colon_parens.txt +++ b/test/prism/snapshots/seattlerb/call_colon_parens.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: (1,1)-(1,3) = "::" ├── name: :call ├── message_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_div.txt b/test/prism/snapshots/seattlerb/call_div.txt index bc4e4c94cf1df7..ba62fb87bd1b62 100644 --- a/test/prism/snapshots/seattlerb/call_div.txt +++ b/test/prism/snapshots/seattlerb/call_div.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :/ ├── message_loc: (1,2)-(1,3) = "/" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_dot_parens.txt b/test/prism/snapshots/seattlerb/call_dot_parens.txt index 8c0989c7bc2283..c9b708469967f6 100644 --- a/test/prism/snapshots/seattlerb/call_dot_parens.txt +++ b/test/prism/snapshots/seattlerb/call_dot_parens.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: (1,1)-(1,2) = "." ├── name: :call ├── message_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_eq3.txt b/test/prism/snapshots/seattlerb/call_eq3.txt index 4a31d62679a261..e636e1572572e8 100644 --- a/test/prism/snapshots/seattlerb/call_eq3.txt +++ b/test/prism/snapshots/seattlerb/call_eq3.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :=== ├── message_loc: (1,2)-(1,5) = "===" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_gt.txt b/test/prism/snapshots/seattlerb/call_gt.txt index 5d766435dada8b..a6f19e5adfe4c0 100644 --- a/test/prism/snapshots/seattlerb/call_gt.txt +++ b/test/prism/snapshots/seattlerb/call_gt.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :> ├── message_loc: (1,2)-(1,3) = ">" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_kwsplat.txt b/test/prism/snapshots/seattlerb/call_kwsplat.txt index f3570bbe1353a1..4199e97a44c6fe 100644 --- a/test/prism/snapshots/seattlerb/call_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_kwsplat.txt @@ -20,7 +20,8 @@ │ └── @ AssocSplatNode (location: (1,2)-(1,5)) │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,2)-(1,4) = "**" ├── closing_loc: (1,5)-(1,6) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_lt.txt b/test/prism/snapshots/seattlerb/call_lt.txt index 11308d46646e1d..14f50585d935d5 100644 --- a/test/prism/snapshots/seattlerb/call_lt.txt +++ b/test/prism/snapshots/seattlerb/call_lt.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :< ├── message_loc: (1,2)-(1,3) = "<" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_lte.txt b/test/prism/snapshots/seattlerb/call_lte.txt index 3bf6cfd4337537..665a99d60a8191 100644 --- a/test/prism/snapshots/seattlerb/call_lte.txt +++ b/test/prism/snapshots/seattlerb/call_lte.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :<= ├── message_loc: (1,2)-(1,4) = "<=" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_not.txt b/test/prism/snapshots/seattlerb/call_not.txt index a370633ed3a26f..86c68923031764 100644 --- a/test/prism/snapshots/seattlerb/call_not.txt +++ b/test/prism/snapshots/seattlerb/call_not.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,4)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── call_operator_loc: ∅ ├── name: :! ├── message_loc: (1,0)-(1,3) = "not" diff --git a/test/prism/snapshots/seattlerb/call_pipe.txt b/test/prism/snapshots/seattlerb/call_pipe.txt index 2300d68c77c0ad..855e986ef6f30a 100644 --- a/test/prism/snapshots/seattlerb/call_pipe.txt +++ b/test/prism/snapshots/seattlerb/call_pipe.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :| ├── message_loc: (1,2)-(1,3) = "|" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_rshift.txt b/test/prism/snapshots/seattlerb/call_rshift.txt index 53fcc9cbbeeace..26e593db187a6f 100644 --- a/test/prism/snapshots/seattlerb/call_rshift.txt +++ b/test/prism/snapshots/seattlerb/call_rshift.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :>> ├── message_loc: (1,2)-(1,4) = ">>" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_self_brackets.txt b/test/prism/snapshots/seattlerb/call_self_brackets.txt index 0e03b3dfdfcdf3..16ca69b5c29d38 100644 --- a/test/prism/snapshots/seattlerb/call_self_brackets.txt +++ b/test/prism/snapshots/seattlerb/call_self_brackets.txt @@ -16,6 +16,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,6)-(1,7) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_spaceship.txt b/test/prism/snapshots/seattlerb/call_spaceship.txt index 450a45b749b0bb..8d43c3f971049f 100644 --- a/test/prism/snapshots/seattlerb/call_spaceship.txt +++ b/test/prism/snapshots/seattlerb/call_spaceship.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :<=> ├── message_loc: (1,2)-(1,5) = "<=>" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt b/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt index 295a68dcba189a..242db9e9cb59e4 100644 --- a/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt +++ b/test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt @@ -24,7 +24,8 @@ │ @ StatementsNode (location: (1,8)-(1,9)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,14)-(1,22)) @@ -34,6 +35,7 @@ │ @ StatementsNode (location: (1,17)-(1,18)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,17)-(1,18)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: (1,14)-(1,16) = "do" └── closing_loc: (1,19)-(1,22) = "end" diff --git a/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt b/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt index ee2a20aabdc5d2..7c3ab8dad8fdee 100644 --- a/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt +++ b/test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt @@ -24,7 +24,8 @@ │ @ StatementsNode (location: (1,7)-(1,8)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: @ BlockNode (location: (1,11)-(1,19)) @@ -34,6 +35,7 @@ │ @ StatementsNode (location: (1,14)-(1,15)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,14)-(1,15)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: (1,11)-(1,13) = "do" └── closing_loc: (1,16)-(1,19) = "end" diff --git a/test/prism/snapshots/seattlerb/call_star.txt b/test/prism/snapshots/seattlerb/call_star.txt index ba3099a0c63691..49aee1672c7228 100644 --- a/test/prism/snapshots/seattlerb/call_star.txt +++ b/test/prism/snapshots/seattlerb/call_star.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :* ├── message_loc: (1,2)-(1,3) = "*" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_star2.txt b/test/prism/snapshots/seattlerb/call_star2.txt index d6f112fc2c2927..cc2532cc7c8490 100644 --- a/test/prism/snapshots/seattlerb/call_star2.txt +++ b/test/prism/snapshots/seattlerb/call_star2.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :** ├── message_loc: (1,2)-(1,4) = "**" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_trailing_comma.txt b/test/prism/snapshots/seattlerb/call_trailing_comma.txt index 84c34d2e9eea07..fe28a3ad3eb6fb 100644 --- a/test/prism/snapshots/seattlerb/call_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/call_trailing_comma.txt @@ -15,6 +15,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,2)-(1,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,4)-(1,5) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/call_unary_bang.txt b/test/prism/snapshots/seattlerb/call_unary_bang.txt index 03b295254ac711..782cc83b1037ec 100644 --- a/test/prism/snapshots/seattlerb/call_unary_bang.txt +++ b/test/prism/snapshots/seattlerb/call_unary_bang.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,1)-(1,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :! ├── message_loc: (1,0)-(1,1) = "!" diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index 496909e4df0f9a..6a1cc56da6ba26 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -193,7 +193,8 @@ │ │ │ ├── left: ∅ │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (22,7)-(22,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 10 │ │ │ └── operator_loc: (22,4)-(22,7) = "..." │ │ ├── statements: ∅ │ │ ├── in_loc: (22,0)-(22,2) = "in" @@ -217,7 +218,8 @@ │ │ │ ├── left: ∅ │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (26,6)-(26,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 10 │ │ │ └── operator_loc: (26,4)-(26,6) = ".." │ │ ├── statements: ∅ │ │ ├── in_loc: (26,0)-(26,2) = "in" @@ -240,7 +242,8 @@ │ │ │ ├── flags: exclude_end │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── right: ∅ │ │ │ └── operator_loc: (30,5)-(30,8) = "..." │ │ ├── statements: ∅ @@ -264,10 +267,12 @@ │ │ │ ├── flags: exclude_end │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (34,4)-(34,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (34,8)-(34,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 3 │ │ │ └── operator_loc: (34,5)-(34,8) = "..." │ │ ├── statements: ∅ │ │ ├── in_loc: (34,0)-(34,2) = "in" @@ -287,7 +292,8 @@ │ │ └── @ InNode (location: (38,0)-(38,6)) │ │ ├── pattern: │ │ │ @ IntegerNode (location: (38,4)-(38,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── statements: ∅ │ │ ├── in_loc: (38,0)-(38,2) = "in" │ │ └── then_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_67.txt b/test/prism/snapshots/seattlerb/case_in_67.txt index 72c7f567635ace..4bab417d578b17 100644 --- a/test/prism/snapshots/seattlerb/case_in_67.txt +++ b/test/prism/snapshots/seattlerb/case_in_67.txt @@ -18,7 +18,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (2,4)-(2,6) = ".." │ ├── statements: diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt index 052468bcc43823..4c8cfd0e544974 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt @@ -29,7 +29,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (2,8)-(2,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: (2,4)-(2,5) = "(" diff --git a/test/prism/snapshots/seattlerb/cond_unary_minus.txt b/test/prism/snapshots/seattlerb/cond_unary_minus.txt index 0d112d7203290c..b6e12dfb15c80e 100644 --- a/test/prism/snapshots/seattlerb/cond_unary_minus.txt +++ b/test/prism/snapshots/seattlerb/cond_unary_minus.txt @@ -7,7 +7,8 @@ ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ IntegerNode (location: (1,3)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -1 ├── then_keyword_loc: ∅ ├── statements: ∅ ├── consequent: ∅ diff --git a/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt b/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt index 332c7ff302e1ee..b018ac48d4fdd5 100644 --- a/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt +++ b/test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt @@ -20,4 +20,5 @@ ├── operator_loc: (1,7)-(1,10) = "||=" └── value: @ IntegerNode (location: (1,11)-(1,12)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt b/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt index e7130cc1b389ff..8d9d94931b9e5f 100644 --- a/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt +++ b/test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt @@ -14,4 +14,5 @@ ├── operator_loc: (1,4)-(1,7) = "||=" └── value: @ IntegerNode (location: (1,8)-(1,9)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt index c4c5534f9297df..b1d61b3752c594 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt @@ -14,5 +14,6 @@ ├── operator_loc: (1,4)-(1,6) = "&=" ├── value: │ @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── operator: :& diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt b/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt index ef9ee358b991dd..22f66825349342 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_and2.txt @@ -14,4 +14,5 @@ ├── operator_loc: (1,4)-(1,7) = "&&=" └── value: @ IntegerNode (location: (1,8)-(1,9)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_or.txt b/test/prism/snapshots/seattlerb/const_op_asgn_or.txt index 7afc8882e99f14..067e0fbb93d7eb 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_or.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_or.txt @@ -16,4 +16,5 @@ ├── operator_loc: (1,5)-(1,8) = "||=" └── value: @ IntegerNode (location: (1,9)-(1,10)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/defined_eh_parens.txt b/test/prism/snapshots/seattlerb/defined_eh_parens.txt index b03666c7e4a4be..49b577fcd13431 100644 --- a/test/prism/snapshots/seattlerb/defined_eh_parens.txt +++ b/test/prism/snapshots/seattlerb/defined_eh_parens.txt @@ -7,6 +7,7 @@ ├── lparen_loc: (1,8)-(1,9) = "(" ├── value: │ @ IntegerNode (location: (1,9)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── rparen_loc: (1,11)-(1,12) = ")" └── keyword_loc: (1,0)-(1,8) = "defined?" diff --git a/test/prism/snapshots/seattlerb/defn_endless_command.txt b/test/prism/snapshots/seattlerb/defn_endless_command.txt index b75ef779bb1246..c3ea59282a7e90 100644 --- a/test/prism/snapshots/seattlerb/defn_endless_command.txt +++ b/test/prism/snapshots/seattlerb/defn_endless_command.txt @@ -23,7 +23,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,31)-(1,33)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt b/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt index 487be865ea2929..dfd1d01ba828a1 100644 --- a/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt +++ b/test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt @@ -25,13 +25,15 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,31)-(1,33)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (1,34)-(1,40) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,41)-(1,43)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 24 ├── locals: [] ├── def_keyword_loc: (1,0)-(1,3) = "def" ├── operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt index d0f2cbada66924..8a5022ff37d45c 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt @@ -23,14 +23,16 @@ │ │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ OptionalKeywordParameterNode (location: (1,15)-(1,19)) │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,15)-(1,17) = "c:" │ │ └── value: │ │ @ IntegerNode (location: (1,18)-(1,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt index d6e867d77d3cbd..4c980bc27f8055 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,15)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt index f5fb41836ab612..40afacc2a7d1b9 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,14)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt index 67d120e13be25a..bc5747ad02dc07 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt index 2b52aff2ca0608..82527f7875fa18 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt @@ -23,7 +23,8 @@ │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt index be3dd8cb9980e6..2708351ede4256 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt @@ -34,7 +34,8 @@ │ │ @ StatementsNode (location: (2,14)-(2,16)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,14)-(2,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [:o] │ ├── def_keyword_loc: (2,2)-(2,5) = "def" │ ├── operator_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt index ba394bbf1ad8e3..3019e9b73e371c 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt @@ -18,7 +18,8 @@ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ └── value: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── rest: │ │ @ RestParameterNode (location: (1,14)-(1,16)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_endless_command.txt b/test/prism/snapshots/seattlerb/defs_endless_command.txt index 70471e97ad2256..f3c4e7941788f9 100644 --- a/test/prism/snapshots/seattlerb/defs_endless_command.txt +++ b/test/prism/snapshots/seattlerb/defs_endless_command.txt @@ -33,7 +33,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,33)-(1,35)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── closing_loc: ∅ │ └── block: ∅ ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt b/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt index 1848d4233e6d16..b0cd34a9c831f6 100644 --- a/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt +++ b/test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt @@ -35,13 +35,15 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,33)-(1,35)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (1,36)-(1,42) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,43)-(1,45)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 24 ├── locals: [] ├── def_keyword_loc: (1,0)-(1,3) = "def" ├── operator_loc: (1,5)-(1,6) = "." diff --git a/test/prism/snapshots/seattlerb/defs_kwarg.txt b/test/prism/snapshots/seattlerb/defs_kwarg.txt index 4a481ffe878618..53235c9bb80f86 100644 --- a/test/prism/snapshots/seattlerb/defs_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defs_kwarg.txt @@ -21,7 +21,8 @@ │ │ ├── name_loc: (1,11)-(1,13) = "b:" │ │ └── value: │ │ @ IntegerNode (location: (1,14)-(1,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt index 15843bb1f8e38a..fcc5c63cf06323 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt @@ -35,7 +35,8 @@ │ │ @ StatementsNode (location: (2,19)-(2,21)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,19)-(2,21)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [:o] │ ├── def_keyword_loc: (2,2)-(2,5) = "def" │ ├── operator_loc: (2,10)-(2,11) = "." diff --git a/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt b/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt index 134993db015116..da2306312c7fc2 100644 --- a/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt +++ b/test/prism/snapshots/seattlerb/difficult1_line_numbers.txt @@ -23,7 +23,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (2,4)-(2,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (3,2)-(3,7)) @@ -48,7 +49,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (4,2)-(4,10)) @@ -73,9 +75,11 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (4,6)-(4,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 3 │ │ │ └── @ IntegerNode (location: (4,9)-(4,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 4 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (5,2)-(5,7)) @@ -100,7 +104,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 5 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (6,2)-(6,10)) @@ -125,9 +130,11 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (6,6)-(6,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 6 │ │ │ └── @ IntegerNode (location: (6,9)-(6,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 7 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── @ CallNode (location: (7,2)-(7,6)) @@ -142,7 +149,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,4)-(7,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (7,5)-(7,6) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (8,2)-(8,8)) @@ -167,7 +175,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (8,6)-(8,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: (8,7)-(8,8) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (9,2)-(9,11)) @@ -192,9 +201,11 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (9,6)-(9,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 3 │ │ │ └── @ IntegerNode (location: (9,9)-(9,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 4 │ │ ├── closing_loc: (9,10)-(9,11) = ")" │ │ └── block: ∅ │ ├── @ CallNode (location: (10,2)-(10,8)) @@ -219,7 +230,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (10,6)-(10,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 5 │ │ ├── closing_loc: (10,7)-(10,8) = ")" │ │ └── block: ∅ │ └── @ CallNode (location: (11,2)-(11,11)) @@ -244,9 +256,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (11,6)-(11,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 6 │ │ └── @ IntegerNode (location: (11,9)-(11,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 7 │ ├── closing_loc: (11,10)-(11,11) = ")" │ └── block: ∅ ├── consequent: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt b/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt index 014b6881271249..f586634c59b1f0 100644 --- a/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt +++ b/test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt @@ -36,7 +36,8 @@ │ │ │ ├── name_loc: (3,2)-(3,3) = "b" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (3,4)-(3,5) = "=" │ │ ├── @ CallNode (location: (4,2)-(4,5)) │ │ │ ├── flags: ignore_visibility @@ -60,7 +61,8 @@ │ │ ├── name_loc: (5,2)-(5,3) = "c" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,5)-(5,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (5,4)-(5,5) = "=" │ ├── consequent: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" diff --git a/test/prism/snapshots/seattlerb/difficult2_.txt b/test/prism/snapshots/seattlerb/difficult2_.txt index 6680a28d6c6763..a9b3736fe33cf0 100644 --- a/test/prism/snapshots/seattlerb/difficult2_.txt +++ b/test/prism/snapshots/seattlerb/difficult2_.txt @@ -7,7 +7,8 @@ │ ├── if_keyword_loc: ∅ │ ├── predicate: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── then_keyword_loc: (1,2)-(1,3) = "?" │ ├── statements: │ │ @ StatementsNode (location: (1,4)-(1,9)) @@ -38,7 +39,8 @@ │ │ │ @ StatementsNode (location: (1,12)-(1,13)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ └── @ CallNode (location: (2,0)-(2,6)) @@ -65,7 +67,8 @@ │ │ └── unescaped: "d" │ ├── value: │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: ∅ ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt b/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt index c5868e193cf3cc..ee4370c0f03971 100644 --- a/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt +++ b/test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt @@ -4,11 +4,13 @@ @ StatementsNode (location: (1,0)-(2,3)) └── body: (length: 2) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ RangeNode (location: (2,0)-(2,3)) ├── flags: ∅ ├── left: ∅ ├── right: │ @ IntegerNode (location: (2,2)-(2,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 └── operator_loc: (2,0)-(2,2) = ".." diff --git a/test/prism/snapshots/seattlerb/difficult6__7.txt b/test/prism/snapshots/seattlerb/difficult6__7.txt index a135b3b41b6f16..7fe70c7033279f 100644 --- a/test/prism/snapshots/seattlerb/difficult6__7.txt +++ b/test/prism/snapshots/seattlerb/difficult6__7.txt @@ -29,7 +29,8 @@ │ │ @ StatementsNode (location: (1,5)-(1,6)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (1,4)-(1,5) = "(" │ └── closing_loc: (1,6)-(1,7) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult6__8.txt b/test/prism/snapshots/seattlerb/difficult6__8.txt index a19057e44b2a58..7f915e283c73df 100644 --- a/test/prism/snapshots/seattlerb/difficult6__8.txt +++ b/test/prism/snapshots/seattlerb/difficult6__8.txt @@ -29,7 +29,8 @@ │ │ @ StatementsNode (location: (1,6)-(1,7)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (1,5)-(1,6) = "(" │ └── closing_loc: (1,7)-(1,8) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/do_bug.txt b/test/prism/snapshots/seattlerb/do_bug.txt index fa13e431d58cbe..5877b18d686d55 100644 --- a/test/prism/snapshots/seattlerb/do_bug.txt +++ b/test/prism/snapshots/seattlerb/do_bug.txt @@ -15,7 +15,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (2,0)-(4,3)) diff --git a/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt b/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt index 1fd43f61663e3e..a5fc3951d69d2d 100644 --- a/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt +++ b/test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt @@ -4,6 +4,8 @@ @ StatementsNode (location: (1,0)-(6,1)) └── body: (length: 2) ├── @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ IntegerNode (location: (6,0)-(6,1)) - └── flags: decimal + ├── flags: decimal + └── value: 2 diff --git a/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt b/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt index 6c28ff4ebe514c..2103bde8cbfa76 100644 --- a/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt +++ b/test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt @@ -40,7 +40,8 @@ │ │ @ StatementsNode (location: (2,7)-(2,9)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (2,7)-(2,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── rescue_clause: ∅ │ ├── else_clause: ∅ │ ├── ensure_clause: ∅ diff --git a/test/prism/snapshots/seattlerb/f_kw.txt b/test/prism/snapshots/seattlerb/f_kw.txt index dfb79f98c9d8f0..4226137925ae02 100644 --- a/test/prism/snapshots/seattlerb/f_kw.txt +++ b/test/prism/snapshots/seattlerb/f_kw.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,8) = "k:" │ │ └── value: │ │ @ IntegerNode (location: (1,8)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/seattlerb/heredoc_lineno.txt b/test/prism/snapshots/seattlerb/heredoc_lineno.txt index eb632218a4d9c4..a51ce71afe83ca 100644 --- a/test/prism/snapshots/seattlerb/heredoc_lineno.txt +++ b/test/prism/snapshots/seattlerb/heredoc_lineno.txt @@ -21,5 +21,6 @@ ├── name_loc: (7,0)-(7,1) = "d" ├── value: │ @ IntegerNode (location: (7,4)-(7,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 └── operator_loc: (7,2)-(7,3) = "=" diff --git a/test/prism/snapshots/seattlerb/heredoc_nested.txt b/test/prism/snapshots/seattlerb/heredoc_nested.txt index fde81dd586829a..4734068ba01cca 100644 --- a/test/prism/snapshots/seattlerb/heredoc_nested.txt +++ b/test/prism/snapshots/seattlerb/heredoc_nested.txt @@ -35,6 +35,7 @@ │ │ │ └── unescaped: "a\n" │ │ └── closing_loc: (6,0)-(7,0) = "A\n" │ └── @ IntegerNode (location: (7,0)-(7,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── opening_loc: (1,0)-(1,1) = "[" └── closing_loc: (7,1)-(7,2) = "]" diff --git a/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt b/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt index 8602ed37312d10..31360286c4edc1 100644 --- a/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt +++ b/test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt @@ -29,7 +29,8 @@ │ │ │ │ @ StatementsNode (location: (3,5)-(3,7)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,5)-(3,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 42 │ │ │ └── closing_loc: (3,7)-(3,8) = "}" │ │ ├── @ StringNode (location: (3,8)-(4,0)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/if_elsif.txt b/test/prism/snapshots/seattlerb/if_elsif.txt index 8ce1864e7643ee..034850158c29fb 100644 --- a/test/prism/snapshots/seattlerb/if_elsif.txt +++ b/test/prism/snapshots/seattlerb/if_elsif.txt @@ -7,7 +7,8 @@ ├── if_keyword_loc: (1,0)-(1,2) = "if" ├── predicate: │ @ IntegerNode (location: (1,3)-(1,4)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── then_keyword_loc: ∅ ├── statements: ∅ ├── consequent: @@ -15,7 +16,8 @@ │ ├── if_keyword_loc: (1,6)-(1,11) = "elsif" │ ├── predicate: │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── then_keyword_loc: ∅ │ ├── statements: ∅ │ ├── consequent: ∅ diff --git a/test/prism/snapshots/seattlerb/integer_with_if_modifier.txt b/test/prism/snapshots/seattlerb/integer_with_if_modifier.txt index 7e0c8a2365db02..2108c1f0a0a464 100644 --- a/test/prism/snapshots/seattlerb/integer_with_if_modifier.txt +++ b/test/prism/snapshots/seattlerb/integer_with_if_modifier.txt @@ -12,6 +12,7 @@ │ @ StatementsNode (location: (1,0)-(1,5)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,0)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1234 ├── consequent: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt b/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt index 955cd210330395..ab231cf539ae0b 100644 --- a/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt @@ -21,4 +21,5 @@ │ ├── opening_loc: (1,0)-(1,3) = "%I(" │ └── closing_loc: (4,0)-(4,1) = ")" └── @ IntegerNode (location: (5,0)-(5,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt b/test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt index bc28bf857414ea..933e5de62723d1 100644 --- a/test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt @@ -21,4 +21,5 @@ │ ├── opening_loc: (1,0)-(1,3) = "%W(" │ └── closing_loc: (4,0)-(4,1) = ")" └── @ IntegerNode (location: (5,0)-(5,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/iter_args_10_1.txt b/test/prism/snapshots/seattlerb/iter_args_10_1.txt index 14dbdc3c034d5f..b8aaae800a5ed2 100644 --- a/test/prism/snapshots/seattlerb/iter_args_10_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_10_1.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_10_2.txt b/test/prism/snapshots/seattlerb/iter_args_10_2.txt index c0bc6d4362a1e0..833f6429dc7ac9 100644 --- a/test/prism/snapshots/seattlerb/iter_args_10_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_10_2.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_11_1.txt b/test/prism/snapshots/seattlerb/iter_args_11_1.txt index c7f86d414d20f6..e4d2f794742d09 100644 --- a/test/prism/snapshots/seattlerb/iter_args_11_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_11_1.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_11_2.txt b/test/prism/snapshots/seattlerb/iter_args_11_2.txt index 545f279008dff0..07a0e5ed9dbf46 100644 --- a/test/prism/snapshots/seattlerb/iter_args_11_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_11_2.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_6.txt b/test/prism/snapshots/seattlerb/iter_args_6.txt index 768a5df47d5071..df3a405dffdf99 100644 --- a/test/prism/snapshots/seattlerb/iter_args_6.txt +++ b/test/prism/snapshots/seattlerb/iter_args_6.txt @@ -31,7 +31,8 @@ │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,10)-(1,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,15)) diff --git a/test/prism/snapshots/seattlerb/iter_args_7_1.txt b/test/prism/snapshots/seattlerb/iter_args_7_1.txt index 738c5f71ff5168..3f65fb8dc0b32c 100644 --- a/test/prism/snapshots/seattlerb/iter_args_7_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_7_1.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_7_2.txt b/test/prism/snapshots/seattlerb/iter_args_7_2.txt index da9cf45c0f1bf7..112a5a1b6b6438 100644 --- a/test/prism/snapshots/seattlerb/iter_args_7_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_7_2.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_8_1.txt b/test/prism/snapshots/seattlerb/iter_args_8_1.txt index 4811772657c92c..5591fcfc695cb6 100644 --- a/test/prism/snapshots/seattlerb/iter_args_8_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_8_1.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_8_2.txt b/test/prism/snapshots/seattlerb/iter_args_8_2.txt index a2019fce1baa7e..8cb061d5a7a1cd 100644 --- a/test/prism/snapshots/seattlerb/iter_args_8_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_8_2.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_9_1.txt b/test/prism/snapshots/seattlerb/iter_args_9_1.txt index 5655080be4cf79..70b2a6cb1910a4 100644 --- a/test/prism/snapshots/seattlerb/iter_args_9_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_9_1.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/iter_args_9_2.txt b/test/prism/snapshots/seattlerb/iter_args_9_2.txt index ba2165866045e8..cad8b47e7f620f 100644 --- a/test/prism/snapshots/seattlerb/iter_args_9_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_9_2.txt @@ -28,7 +28,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) diff --git a/test/prism/snapshots/seattlerb/iter_kwarg.txt b/test/prism/snapshots/seattlerb/iter_kwarg.txt index f5968e33402e37..13b90276617e85 100644 --- a/test/prism/snapshots/seattlerb/iter_kwarg.txt +++ b/test/prism/snapshots/seattlerb/iter_kwarg.txt @@ -30,7 +30,8 @@ │ │ │ ├── name_loc: (1,5)-(1,7) = "b:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── locals: (length: 0) diff --git a/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt b/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt index 14276baf887f21..321e15cb2bcfba 100644 --- a/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt @@ -30,7 +30,8 @@ │ │ │ ├── name_loc: (1,5)-(1,7) = "b:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (1,11)-(1,14)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt b/test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt index b1c234bff2445a..7bbef7055a1a76 100644 --- a/test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt +++ b/test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt @@ -11,9 +11,11 @@ │ @ RescueModifierNode (location: (1,4)-(1,14)) │ ├── expression: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_loc: (1,6)-(1,12) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,13)-(1,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt b/test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt index 9d19aea652d41c..521fceaf1b7242 100644 --- a/test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt +++ b/test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt @@ -22,11 +22,13 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (1,7)-(1,8) = ")" │ │ └── block: ∅ │ ├── keyword_loc: (1,9)-(1,15) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,16)-(1,17)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt b/test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt index ded4704a59f03b..d730fb51cbe687 100644 --- a/test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt +++ b/test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt @@ -22,11 +22,13 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── keyword_loc: (1,8)-(1,14) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (1,15)-(1,16)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_command.txt b/test/prism/snapshots/seattlerb/lasgn_command.txt index 4b2409069ca53e..d6ed787b26b7dc 100644 --- a/test/prism/snapshots/seattlerb/lasgn_command.txt +++ b/test/prism/snapshots/seattlerb/lasgn_command.txt @@ -30,7 +30,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_env.txt b/test/prism/snapshots/seattlerb/lasgn_env.txt index 33539a69182da5..a0ada99a9bc01c 100644 --- a/test/prism/snapshots/seattlerb/lasgn_env.txt +++ b/test/prism/snapshots/seattlerb/lasgn_env.txt @@ -9,5 +9,6 @@ ├── name_loc: (1,0)-(1,1) = "a" ├── value: │ @ IntegerNode (location: (1,4)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 └── operator_loc: (1,2)-(1,3) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_ivar_env.txt b/test/prism/snapshots/seattlerb/lasgn_ivar_env.txt index e37a331d51fd27..5675730477052f 100644 --- a/test/prism/snapshots/seattlerb/lasgn_ivar_env.txt +++ b/test/prism/snapshots/seattlerb/lasgn_ivar_env.txt @@ -8,5 +8,6 @@ ├── name_loc: (1,0)-(1,2) = "@a" ├── value: │ @ IntegerNode (location: (1,5)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 └── operator_loc: (1,3)-(1,4) = "=" diff --git a/test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt b/test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt index c11ae14e19a7bd..bb4b64e88cdaca 100644 --- a/test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt +++ b/test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt @@ -25,7 +25,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── operator_loc: (1,6)-(1,7) = "=" diff --git a/test/prism/snapshots/seattlerb/masgn_colon2.txt b/test/prism/snapshots/seattlerb/masgn_colon2.txt index eb445420d37e04..73ce8a71da2c7b 100644 --- a/test/prism/snapshots/seattlerb/masgn_colon2.txt +++ b/test/prism/snapshots/seattlerb/masgn_colon2.txt @@ -34,8 +34,10 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,13)-(1,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: ∅ └── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/masgn_colon3.txt b/test/prism/snapshots/seattlerb/masgn_colon3.txt index f2880a4426cf72..0cf4f8626d580e 100644 --- a/test/prism/snapshots/seattlerb/masgn_colon3.txt +++ b/test/prism/snapshots/seattlerb/masgn_colon3.txt @@ -27,8 +27,10 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,14)-(1,15)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: ∅ └── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/masgn_command_call.txt b/test/prism/snapshots/seattlerb/masgn_command_call.txt index aa0d17e436d424..687ea382436931 100644 --- a/test/prism/snapshots/seattlerb/masgn_command_call.txt +++ b/test/prism/snapshots/seattlerb/masgn_command_call.txt @@ -37,6 +37,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,9)-(1,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/masgn_lhs_splat.txt b/test/prism/snapshots/seattlerb/masgn_lhs_splat.txt index 7615d7d02bb683..771dd7c0406527 100644 --- a/test/prism/snapshots/seattlerb/masgn_lhs_splat.txt +++ b/test/prism/snapshots/seattlerb/masgn_lhs_splat.txt @@ -21,10 +21,13 @@ ├── flags: ∅ ├── elements: (length: 3) │ ├── @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (1,11)-(1,12)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── opening_loc: ∅ └── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/masgn_star.txt b/test/prism/snapshots/seattlerb/masgn_star.txt index 22783c909d23b8..3e01eef8a78c72 100644 --- a/test/prism/snapshots/seattlerb/masgn_star.txt +++ b/test/prism/snapshots/seattlerb/masgn_star.txt @@ -15,4 +15,5 @@ ├── operator_loc: (1,2)-(1,3) = "=" └── value: @ IntegerNode (location: (1,4)-(1,5)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt b/test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt index 6947ec4187fce6..da10a474c3a3c5 100644 --- a/test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt @@ -30,10 +30,12 @@ │ └── @ AssocNode (location: (1,4)-(1,8)) │ ├── key: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (1,5)-(1,7) = "=>" ├── closing_loc: (1,9)-(1,10) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/method_call_trailing_comma.txt b/test/prism/snapshots/seattlerb/method_call_trailing_comma.txt index 9fee71b503166f..edf79062cfe636 100644 --- a/test/prism/snapshots/seattlerb/method_call_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/method_call_trailing_comma.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,6)-(1,7) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/mlhs_rescue.txt b/test/prism/snapshots/seattlerb/mlhs_rescue.txt index 3fe7f92d84e4d9..bd983cd3f9bf42 100644 --- a/test/prism/snapshots/seattlerb/mlhs_rescue.txt +++ b/test/prism/snapshots/seattlerb/mlhs_rescue.txt @@ -32,4 +32,5 @@ ├── keyword_loc: (1,9)-(1,15) = "rescue" └── rescue_expression: @ IntegerNode (location: (1,16)-(1,18)) - └── flags: decimal + ├── flags: decimal + └── value: 42 diff --git a/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt b/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt index a39a6c12559095..cbf4ec4a081e76 100644 --- a/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt @@ -21,4 +21,5 @@ │ ├── opening_loc: (1,0)-(1,3) = "%i(" │ └── closing_loc: (4,0)-(4,1) = ")" └── @ IntegerNode (location: (5,0)-(5,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt b/test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt index 705ab476d63983..e82f250098123e 100644 --- a/test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt @@ -21,4 +21,5 @@ │ ├── opening_loc: (1,0)-(1,3) = "%w(" │ └── closing_loc: (4,0)-(4,1) = ")" └── @ IntegerNode (location: (5,0)-(5,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/op_asgn_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_command_call.txt index cd97d440d34a01..54aa06214fa27a 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_command_call.txt @@ -29,7 +29,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: ∅ │ └── block: ∅ ├── name: :a diff --git a/test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt index edf54a0c29ba14..324c042b00d829 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt @@ -26,6 +26,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt index 9221c717c7a1e1..ddee4cde495033 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt @@ -44,8 +44,10 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,12)-(1,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,15)-(1,16)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt index 0416e0fa71a85f..0daadcf6ff6213 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt @@ -16,4 +16,5 @@ ├── operator_loc: (1,5)-(1,7) = "+=" └── value: @ IntegerNode (location: (1,8)-(1,9)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt index 1fcad3e307b9a6..b3b5709193886d 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt @@ -34,6 +34,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_block.txt b/test/prism/snapshots/seattlerb/parse_line_block.txt index d5f5ee084b18ed..623c08d50e3ca3 100644 --- a/test/prism/snapshots/seattlerb/parse_line_block.txt +++ b/test/prism/snapshots/seattlerb/parse_line_block.txt @@ -9,7 +9,8 @@ │ ├── name_loc: (1,0)-(1,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ └── operator_loc: (1,2)-(1,3) = "=" └── @ CallNode (location: (2,0)-(2,3)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt index 9a437d367c92c2..50ccb762bee076 100644 --- a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt +++ b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt @@ -43,7 +43,8 @@ │ │ ├── operator_loc: (3,4)-(3,6) = "*=" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,7)-(3,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── name: :y │ │ ├── operator: :* │ │ └── depth: 0 diff --git a/test/prism/snapshots/seattlerb/parse_line_dot2.txt b/test/prism/snapshots/seattlerb/parse_line_dot2.txt index 4b01940a5fceb1..9ccf5bdc994a9a 100644 --- a/test/prism/snapshots/seattlerb/parse_line_dot2.txt +++ b/test/prism/snapshots/seattlerb/parse_line_dot2.txt @@ -7,10 +7,12 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── right: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ └── operator_loc: (1,1)-(1,3) = ".." ├── @ RangeNode (location: (3,0)-(4,1)) │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_dot2_open.txt b/test/prism/snapshots/seattlerb/parse_line_dot2_open.txt index b78712077273b8..f85fdd6d4b8135 100644 --- a/test/prism/snapshots/seattlerb/parse_line_dot2_open.txt +++ b/test/prism/snapshots/seattlerb/parse_line_dot2_open.txt @@ -7,7 +7,8 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── right: ∅ │ └── operator_loc: (1,1)-(1,3) = ".." ├── @ RangeNode (location: (2,2)-(2,5)) diff --git a/test/prism/snapshots/seattlerb/parse_line_dot3.txt b/test/prism/snapshots/seattlerb/parse_line_dot3.txt index 0b2b90f860a769..6364c1f1366935 100644 --- a/test/prism/snapshots/seattlerb/parse_line_dot3.txt +++ b/test/prism/snapshots/seattlerb/parse_line_dot3.txt @@ -7,10 +7,12 @@ │ ├── flags: exclude_end │ ├── left: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── right: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ └── operator_loc: (1,1)-(1,4) = "..." ├── @ RangeNode (location: (3,0)-(4,1)) │ ├── flags: exclude_end diff --git a/test/prism/snapshots/seattlerb/parse_line_dot3_open.txt b/test/prism/snapshots/seattlerb/parse_line_dot3_open.txt index d2349ddb2b1efa..35759d12e390df 100644 --- a/test/prism/snapshots/seattlerb/parse_line_dot3_open.txt +++ b/test/prism/snapshots/seattlerb/parse_line_dot3_open.txt @@ -7,7 +7,8 @@ │ ├── flags: exclude_end │ ├── left: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── right: ∅ │ └── operator_loc: (1,1)-(1,4) = "..." ├── @ RangeNode (location: (2,2)-(2,6)) diff --git a/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt b/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt index 410a54b7e370be..0f95a607aa0b16 100644 --- a/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt +++ b/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt @@ -16,6 +16,7 @@ │ │ └── unescaped: "s1" │ ├── value: │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (2,4)-(2,6) = "=>" └── closing_loc: (3,0)-(3,1) = "}" diff --git a/test/prism/snapshots/seattlerb/parse_line_multiline_str.txt b/test/prism/snapshots/seattlerb/parse_line_multiline_str.txt index fa8c4910477adc..8d4578eaec9e5f 100644 --- a/test/prism/snapshots/seattlerb/parse_line_multiline_str.txt +++ b/test/prism/snapshots/seattlerb/parse_line_multiline_str.txt @@ -10,4 +10,5 @@ │ ├── closing_loc: (2,1)-(2,2) = "\"" │ └── unescaped: "a\nb" └── @ IntegerNode (location: (3,0)-(3,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt b/test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt index c72b516baae789..49d31f5b1b5449 100644 --- a/test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt +++ b/test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt @@ -10,4 +10,5 @@ │ ├── closing_loc: (1,5)-(1,6) = "\"" │ └── unescaped: "a\nb" └── @ IntegerNode (location: (2,0)-(2,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/parse_line_return.txt b/test/prism/snapshots/seattlerb/parse_line_return.txt index 9c4a5a17688a03..9194ae13ee5e19 100644 --- a/test/prism/snapshots/seattlerb/parse_line_return.txt +++ b/test/prism/snapshots/seattlerb/parse_line_return.txt @@ -26,7 +26,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (3,17)-(3,19)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── consequent: ∅ │ └── end_keyword_loc: (4,8)-(4,11) = "end" ├── locals: [] diff --git a/test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt b/test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt index 310507d26a2ecf..b767a5c17e5972 100644 --- a/test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt +++ b/test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :[] ├── message_loc: (1,1)-(1,8) = "[2=>3,]" @@ -22,10 +23,12 @@ │ └── @ AssocNode (location: (1,2)-(1,6)) │ ├── key: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (1,3)-(1,5) = "=>" ├── closing_loc: (1,7)-(1,8) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt b/test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt index c1d086d5f385c7..d1d3d9335f3011 100644 --- a/test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt +++ b/test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt @@ -7,7 +7,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: ∅ ├── name: :[] ├── message_loc: (1,1)-(1,5) = "[2,]" @@ -17,6 +18,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,2)-(1,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: (1,4)-(1,5) = "]" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_pattern_019.txt b/test/prism/snapshots/seattlerb/parse_pattern_019.txt index 2ba406f186c9ae..9e2500fbdefe39 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_019.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_019.txt @@ -6,7 +6,8 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── conditions: (length: 1) │ └── @ InNode (location: (2,0)-(3,6)) │ ├── pattern: @@ -14,10 +15,12 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (2,3)-(2,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: -1 │ │ ├── right: │ │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (2,5)-(2,7) = ".." │ ├── statements: │ │ @ StatementsNode (location: (3,2)-(3,6)) diff --git a/test/prism/snapshots/seattlerb/parse_pattern_051.txt b/test/prism/snapshots/seattlerb/parse_pattern_051.txt index 6ae0944d100486..6c366e559f6718 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_051.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_051.txt @@ -9,11 +9,14 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 0 │ │ ├── @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (1,5)-(1,6) = "[" │ └── closing_loc: (1,13)-(1,14) = "]" ├── conditions: (length: 1) @@ -23,9 +26,11 @@ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ IntegerNode (location: (2,4)-(2,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ └── @ IntegerNode (location: (2,7)-(2,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ ImplicitRestNode (location: (2,8)-(2,9)) │ │ ├── posts: (length: 0) diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058.txt b/test/prism/snapshots/seattlerb/parse_pattern_058.txt index f3ff72c35f295c..8a4f8f8a68cbe8 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058.txt @@ -18,7 +18,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 0 │ │ └── operator_loc: ∅ │ └── closing_loc: (1,10)-(1,11) = "}" ├── conditions: (length: 1) diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt index 383b4d5f2f116e..3507d0f2cf219b 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt @@ -18,7 +18,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 0 │ │ └── operator_loc: ∅ │ └── closing_loc: (1,10)-(1,11) = "}" ├── conditions: (length: 1) diff --git a/test/prism/snapshots/seattlerb/parse_pattern_069.txt b/test/prism/snapshots/seattlerb/parse_pattern_069.txt index e76c6d3f147451..09ac7653c6b93a 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_069.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_069.txt @@ -29,7 +29,8 @@ │ │ │ │ └── unescaped: "b" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (2,13)-(2,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: (2,9)-(2,10) = "[" @@ -38,7 +39,8 @@ │ │ @ StatementsNode (location: (3,2)-(3,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (3,2)-(3,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── in_loc: (2,0)-(2,2) = "in" │ └── then_loc: ∅ ├── consequent: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_pattern_076.txt b/test/prism/snapshots/seattlerb/parse_pattern_076.txt index 8ae4b68547bcad..60e71cd6fe9b66 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_076.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_076.txt @@ -18,7 +18,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ └── closing_loc: (1,10)-(1,11) = "}" ├── conditions: (length: 1) @@ -37,7 +38,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (2,7)-(2,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ ├── rest: │ │ │ @ NoKeywordsParameterNode (location: (2,10)-(2,15)) diff --git a/test/prism/snapshots/seattlerb/qsymbols_interp.txt b/test/prism/snapshots/seattlerb/qsymbols_interp.txt index ca300721cc6a70..23c39302475630 100644 --- a/test/prism/snapshots/seattlerb/qsymbols_interp.txt +++ b/test/prism/snapshots/seattlerb/qsymbols_interp.txt @@ -30,7 +30,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: │ │ │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :+ │ │ │ │ ├── message_loc: (1,9)-(1,10) = "+" @@ -40,7 +41,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── closing_loc: (1,11)-(1,12) = "}" diff --git a/test/prism/snapshots/seattlerb/return_call_assocs.txt b/test/prism/snapshots/seattlerb/return_call_assocs.txt index 3acf37174456ac..69aae7b2054b86 100644 --- a/test/prism/snapshots/seattlerb/return_call_assocs.txt +++ b/test/prism/snapshots/seattlerb/return_call_assocs.txt @@ -10,7 +10,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (1,10)-(1,17)) │ ├── flags: symbol_keys │ └── elements: (length: 1) @@ -24,7 +25,8 @@ │ │ └── unescaped: "z" │ ├── value: │ │ @ IntegerNode (location: (1,16)-(1,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,13)-(1,15) = "=>" ├── @ ReturnNode (location: (3,0)-(3,26)) │ ├── keyword_loc: (3,0)-(3,6) = "return" @@ -33,7 +35,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (3,7)-(3,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (3,10)-(3,26)) │ ├── flags: symbol_keys │ └── elements: (length: 2) @@ -47,7 +50,8 @@ │ │ │ └── unescaped: "z" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,16)-(3,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (3,13)-(3,15) = "=>" │ └── @ AssocNode (location: (3,19)-(3,26)) │ ├── key: @@ -59,7 +63,8 @@ │ │ └── unescaped: "w" │ ├── value: │ │ @ IntegerNode (location: (3,25)-(3,26)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (3,22)-(3,24) = "=>" ├── @ ReturnNode (location: (5,0)-(5,14)) │ ├── keyword_loc: (5,0)-(5,6) = "return" @@ -91,7 +96,8 @@ │ │ │ └── unescaped: "z" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,13)-(5,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (5,11)-(5,13) = "=>" │ ├── closing_loc: ∅ │ └── block: ∅ @@ -125,7 +131,8 @@ │ │ │ └── unescaped: "z" │ │ ├── value: │ │ │ @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ @@ -159,7 +166,8 @@ │ │ │ └── unescaped: "z" │ │ ├── value: │ │ │ @ IntegerNode (location: (9,11)-(9,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ ├── closing_loc: (9,12)-(9,13) = ")" │ └── block: ∅ @@ -197,7 +205,8 @@ │ │ └── block: ∅ │ ├── value: │ │ @ IntegerNode (location: (11,12)-(11,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (11,10)-(11,12) = "=>" ├── closing_loc: (11,13)-(11,14) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/rhs_asgn.txt b/test/prism/snapshots/seattlerb/rhs_asgn.txt index 61ed05f4e1a07b..9ee187218bbd9c 100644 --- a/test/prism/snapshots/seattlerb/rhs_asgn.txt +++ b/test/prism/snapshots/seattlerb/rhs_asgn.txt @@ -6,7 +6,8 @@ └── @ MatchRequiredNode (location: (1,0)-(1,7)) ├── value: │ @ IntegerNode (location: (1,0)-(1,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── pattern: │ @ LocalVariableTargetNode (location: (1,6)-(1,7)) │ ├── name: :n diff --git a/test/prism/snapshots/seattlerb/ruby21_numbers.txt b/test/prism/snapshots/seattlerb/ruby21_numbers.txt index e1ad6b924cf92e..34a3452d1b3539 100644 --- a/test/prism/snapshots/seattlerb/ruby21_numbers.txt +++ b/test/prism/snapshots/seattlerb/ruby21_numbers.txt @@ -9,16 +9,19 @@ │ ├── @ ImaginaryNode (location: (1,1)-(1,3)) │ │ └── numeric: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ RationalNode (location: (1,5)-(1,7)) │ │ └── numeric: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ ImaginaryNode (location: (1,9)-(1,12)) │ └── numeric: │ @ RationalNode (location: (1,9)-(1,11)) │ └── numeric: │ @ IntegerNode (location: (1,9)-(1,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── opening_loc: (1,0)-(1,1) = "[" └── closing_loc: (1,12)-(1,13) = "]" diff --git a/test/prism/snapshots/seattlerb/safe_attrasgn.txt b/test/prism/snapshots/seattlerb/safe_attrasgn.txt index 191fc53785777d..3cec95ae7cd696 100644 --- a/test/prism/snapshots/seattlerb/safe_attrasgn.txt +++ b/test/prism/snapshots/seattlerb/safe_attrasgn.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt b/test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt index 10a5cc9495b07b..baea063186405a 100644 --- a/test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt +++ b/test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/safe_call_operator.txt b/test/prism/snapshots/seattlerb/safe_call_operator.txt index a84a348f6ea920..d1f9b1ea9ef26d 100644 --- a/test/prism/snapshots/seattlerb/safe_call_operator.txt +++ b/test/prism/snapshots/seattlerb/safe_call_operator.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/safe_calls.txt b/test/prism/snapshots/seattlerb/safe_calls.txt index 3b17d28026e9e3..54e591d9c0a9be 100644 --- a/test/prism/snapshots/seattlerb/safe_calls.txt +++ b/test/prism/snapshots/seattlerb/safe_calls.txt @@ -35,6 +35,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,9)-(1,10) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/safe_op_asgn.txt b/test/prism/snapshots/seattlerb/safe_op_asgn.txt index 1e00005bd0ff0d..7a9fd2b7f71206 100644 --- a/test/prism/snapshots/seattlerb/safe_op_asgn.txt +++ b/test/prism/snapshots/seattlerb/safe_op_asgn.txt @@ -35,6 +35,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt index c3d70b6a761c23..0b0000ef33519c 100644 --- a/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt @@ -24,7 +24,8 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,11)-(1,13)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt b/test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt index 9489b13a9519a9..d7a268a5d5a5bf 100644 --- a/test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt +++ b/test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt @@ -40,7 +40,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (2,2)-(2,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (2,3)-(2,4) = ")" │ └── block: │ @ BlockNode (location: (2,5)-(3,3)) diff --git a/test/prism/snapshots/seattlerb/stabby_block_kw.txt b/test/prism/snapshots/seattlerb/stabby_block_kw.txt index fd6bab809c8099..7addbb8b288290 100644 --- a/test/prism/snapshots/seattlerb/stabby_block_kw.txt +++ b/test/prism/snapshots/seattlerb/stabby_block_kw.txt @@ -23,7 +23,8 @@ │ │ │ ├── name_loc: (1,4)-(1,6) = "k:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,6)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── locals: (length: 0) diff --git a/test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt b/test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt index 89f20da7b59584..d55d9650685fff 100644 --- a/test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt +++ b/test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt @@ -10,4 +10,5 @@ │ ├── closing_loc: (1,10)-(1,11) = "\"" │ └── unescaped: "\n\n\n\n#" └── @ IntegerNode (location: (2,0)-(2,1)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/seattlerb/str_pct_nested_nested.txt b/test/prism/snapshots/seattlerb/str_pct_nested_nested.txt index 85ad89bc60673f..b9c39c9a93e850 100644 --- a/test/prism/snapshots/seattlerb/str_pct_nested_nested.txt +++ b/test/prism/snapshots/seattlerb/str_pct_nested_nested.txt @@ -26,7 +26,8 @@ │ │ │ │ │ @ StatementsNode (location: (1,11)-(1,12)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (1,11)-(1,12)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── closing_loc: (1,12)-(1,13) = "}" │ │ │ └── closing_loc: (1,13)-(1,14) = "\"" │ │ └── closing_loc: (1,15)-(1,16) = "}" diff --git a/test/prism/snapshots/seattlerb/super_arg.txt b/test/prism/snapshots/seattlerb/super_arg.txt index a7f13a4adfafcb..61b5f0b63137d0 100644 --- a/test/prism/snapshots/seattlerb/super_arg.txt +++ b/test/prism/snapshots/seattlerb/super_arg.txt @@ -11,6 +11,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── rparen_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/thingy.txt b/test/prism/snapshots/seattlerb/thingy.txt index 6fe6882062c8c6..4dd2ac44a653c9 100644 --- a/test/prism/snapshots/seattlerb/thingy.txt +++ b/test/prism/snapshots/seattlerb/thingy.txt @@ -25,7 +25,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,3)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── closing_loc: (1,5)-(1,6) = ")" │ └── block: ∅ └── @ CallNode (location: (3,0)-(3,7)) @@ -50,6 +51,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (3,4)-(3,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── closing_loc: (3,6)-(3,7) = ")" └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/utf8_bom.txt b/test/prism/snapshots/seattlerb/utf8_bom.txt index 05fa1af4630d9c..9f0eb83b052b3b 100644 --- a/test/prism/snapshots/seattlerb/utf8_bom.txt +++ b/test/prism/snapshots/seattlerb/utf8_bom.txt @@ -15,6 +15,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (2,2)-(2,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/seattlerb/words_interp.txt b/test/prism/snapshots/seattlerb/words_interp.txt index 864f826dcbbca5..dfead7d353404b 100644 --- a/test/prism/snapshots/seattlerb/words_interp.txt +++ b/test/prism/snapshots/seattlerb/words_interp.txt @@ -15,7 +15,8 @@ │ │ │ │ @ StatementsNode (location: (1,5)-(1,6)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (1,6)-(1,7) = "}" │ │ └── @ StringNode (location: (1,7)-(1,8)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/seattlerb/yield_arg.txt b/test/prism/snapshots/seattlerb/yield_arg.txt index d297e5acdb95af..22e0c14f837c31 100644 --- a/test/prism/snapshots/seattlerb/yield_arg.txt +++ b/test/prism/snapshots/seattlerb/yield_arg.txt @@ -11,5 +11,6 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 └── rparen_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/yield_call_assocs.txt b/test/prism/snapshots/seattlerb/yield_call_assocs.txt index 28ac198b701a64..c04273f5aa4568 100644 --- a/test/prism/snapshots/seattlerb/yield_call_assocs.txt +++ b/test/prism/snapshots/seattlerb/yield_call_assocs.txt @@ -11,7 +11,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (1,9)-(1,16)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) @@ -25,7 +26,8 @@ │ │ │ └── unescaped: "z" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,15)-(1,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,12)-(1,14) = "=>" │ └── rparen_loc: ∅ ├── @ YieldNode (location: (3,0)-(3,25)) @@ -36,7 +38,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (3,6)-(3,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ KeywordHashNode (location: (3,9)-(3,25)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) @@ -50,7 +53,8 @@ │ │ │ │ └── unescaped: "z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (3,15)-(3,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (3,12)-(3,14) = "=>" │ │ └── @ AssocNode (location: (3,18)-(3,25)) │ │ ├── key: @@ -62,7 +66,8 @@ │ │ │ └── unescaped: "w" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,24)-(3,25)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (3,21)-(3,23) = "=>" │ └── rparen_loc: ∅ ├── @ YieldNode (location: (5,0)-(5,13)) @@ -96,7 +101,8 @@ │ │ │ │ └── unescaped: "z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (5,12)-(5,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (5,10)-(5,12) = "=>" │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -132,7 +138,8 @@ │ │ │ │ └── unescaped: "z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (7,10)-(7,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ @@ -168,7 +175,8 @@ │ │ │ │ └── unescaped: "z" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (9,10)-(9,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ ├── closing_loc: (9,11)-(9,12) = ")" │ │ └── block: ∅ @@ -208,7 +216,8 @@ │ │ │ └── block: ∅ │ │ ├── value: │ │ │ @ IntegerNode (location: (11,11)-(11,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (11,9)-(11,11) = "=>" │ ├── closing_loc: (11,12)-(11,13) = ")" │ └── block: ∅ diff --git a/test/prism/snapshots/super.txt b/test/prism/snapshots/super.txt index 068e407e9de9e2..79f9a5d5a599a3 100644 --- a/test/prism/snapshots/super.txt +++ b/test/prism/snapshots/super.txt @@ -19,7 +19,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── rparen_loc: (5,7)-(5,8) = ")" │ └── block: ∅ ├── @ SuperNode (location: (7,0)-(7,14)) @@ -30,11 +31,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (7,6)-(7,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (7,9)-(7,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (7,12)-(7,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── rparen_loc: (7,13)-(7,14) = ")" │ └── block: ∅ ├── @ SuperNode (location: (9,0)-(9,11)) @@ -83,11 +87,14 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ IntegerNode (location: (15,6)-(15,7)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ IntegerNode (location: (15,9)-(15,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── @ IntegerNode (location: (15,12)-(15,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── rparen_loc: (15,13)-(15,14) = ")" │ └── block: │ @ BlockNode (location: (15,15)-(15,17)) @@ -104,11 +111,14 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (17,6)-(17,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (17,9)-(17,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (17,12)-(17,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── rparen_loc: (17,20)-(17,21) = ")" └── block: @ BlockArgumentNode (location: (17,15)-(17,20)) diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt index 54a385e34678ce..4fbb277c6edc2b 100644 --- a/test/prism/snapshots/symbols.txt +++ b/test/prism/snapshots/symbols.txt @@ -44,7 +44,8 @@ │ │ │ @ StatementsNode (location: (5,7)-(5,8)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (5,7)-(5,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── closing_loc: (5,8)-(5,9) = "}" │ └── closing_loc: (5,9)-(5,10) = "\"" ├── @ ArrayNode (location: (7,0)-(7,20)) @@ -140,16 +141,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 4) │ │ ├── @ IntegerNode (location: (29,1)-(29,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ FloatNode (location: (29,4)-(29,7)) │ │ ├── @ RationalNode (location: (29,9)-(29,11)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (29,9)-(29,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ ImaginaryNode (location: (29,13)-(29,15)) │ │ └── numeric: │ │ @ IntegerNode (location: (29,13)-(29,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (29,0)-(29,1) = "[" │ └── closing_loc: (29,15)-(29,16) = "]" ├── @ SymbolNode (location: (31,0)-(31,2)) @@ -240,7 +244,8 @@ │ │ │ │ │ @ StatementsNode (location: (39,8)-(39,9)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (39,8)-(39,9)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── closing_loc: (39,9)-(39,10) = "}" │ │ │ └── closing_loc: ∅ │ │ ├── @ InterpolatedSymbolNode (location: (39,11)-(39,16)) @@ -252,7 +257,8 @@ │ │ │ │ │ │ @ StatementsNode (location: (39,13)-(39,14)) │ │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (39,13)-(39,14)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 2 │ │ │ │ │ └── closing_loc: (39,14)-(39,15) = "}" │ │ │ │ └── @ StringNode (location: (39,15)-(39,16)) │ │ │ │ ├── flags: ∅ @@ -276,7 +282,8 @@ │ │ │ │ │ @ StatementsNode (location: (39,20)-(39,21)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (39,20)-(39,21)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 3 │ │ │ │ └── closing_loc: (39,21)-(39,22) = "}" │ │ │ └── @ StringNode (location: (39,22)-(39,23)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/ternary_operator.txt b/test/prism/snapshots/ternary_operator.txt index f1d72f810b2466..0277ac88f0c150 100644 --- a/test/prism/snapshots/ternary_operator.txt +++ b/test/prism/snapshots/ternary_operator.txt @@ -279,7 +279,8 @@ │ ├── name_loc: (15,5)-(15,7) = "_a" │ ├── value: │ │ @ IntegerNode (location: (15,9)-(15,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (15,8)-(15,9) = "=" ├── consequent: │ @ ElseNode (location: (15,10)-(15,12)) @@ -288,6 +289,7 @@ │ │ @ StatementsNode (location: (15,11)-(15,12)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (15,11)-(15,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── end_keyword_loc: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/tilde_heredocs.txt b/test/prism/snapshots/tilde_heredocs.txt index fb09e075e10f0d..fd369a64b2ad00 100644 --- a/test/prism/snapshots/tilde_heredocs.txt +++ b/test/prism/snapshots/tilde_heredocs.txt @@ -18,7 +18,8 @@ │ │ │ │ @ StatementsNode (location: (3,2)-(3,3)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (3,2)-(3,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (3,3)-(3,4) = "}" │ │ ├── @ StringNode (location: (3,4)-(4,0)) │ │ │ ├── flags: ∅ @@ -70,7 +71,8 @@ │ │ │ │ @ StatementsNode (location: (18,4)-(18,5)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (18,4)-(18,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (18,5)-(18,6) = "}" │ │ └── @ StringNode (location: (18,6)-(19,0)) │ │ ├── flags: ∅ @@ -94,7 +96,8 @@ │ │ │ │ @ StatementsNode (location: (22,6)-(22,7)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (22,6)-(22,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (22,7)-(22,8) = "}" │ │ └── @ StringNode (location: (22,8)-(23,0)) │ │ ├── flags: ∅ @@ -118,7 +121,8 @@ │ │ │ │ @ StatementsNode (location: (27,3)-(27,4)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (27,3)-(27,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (27,4)-(27,5) = "}" │ │ └── @ StringNode (location: (27,5)-(28,0)) │ │ ├── flags: ∅ @@ -142,7 +146,8 @@ │ │ │ │ @ StatementsNode (location: (32,4)-(32,5)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (32,4)-(32,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (32,5)-(32,6) = "}" │ │ └── @ StringNode (location: (32,6)-(33,0)) │ │ ├── flags: ∅ @@ -346,7 +351,8 @@ │ │ │ │ @ StatementsNode (location: (91,4)-(91,5)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (91,4)-(91,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (91,5)-(91,6) = "}" │ │ └── @ StringNode (location: (91,6)-(92,0)) │ │ ├── flags: ∅ @@ -364,7 +370,8 @@ │ │ │ @ StatementsNode (location: (95,4)-(95,5)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (95,4)-(95,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── closing_loc: (95,5)-(95,6) = "}" │ ├── @ StringNode (location: (95,6)-(96,0)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/undef.txt b/test/prism/snapshots/undef.txt index 3430ef50599d7d..6031119ad17c77 100644 --- a/test/prism/snapshots/undef.txt +++ b/test/prism/snapshots/undef.txt @@ -101,7 +101,8 @@ │ │ │ │ @ StatementsNode (location: (15,13)-(15,14)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (15,13)-(15,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (15,14)-(15,15) = "}" │ │ └── closing_loc: (15,15)-(15,16) = "\"" │ └── keyword_loc: (15,0)-(15,5) = "undef" diff --git a/test/prism/snapshots/unless.txt b/test/prism/snapshots/unless.txt index 0439e12d379b4b..df16f90fd8efa0 100644 --- a/test/prism/snapshots/unless.txt +++ b/test/prism/snapshots/unless.txt @@ -12,7 +12,8 @@ │ │ @ StatementsNode (location: (1,13)-(1,14)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,13)-(1,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: ∅ │ └── end_keyword_loc: (1,16)-(1,19) = "end" ├── @ UnlessNode (location: (3,0)-(4,12)) @@ -24,7 +25,8 @@ │ │ @ StatementsNode (location: (4,0)-(4,1)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (4,0)-(4,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: │ │ @ ElseNode (location: (4,2)-(4,12)) │ │ ├── else_keyword_loc: (4,2)-(4,6) = "else" @@ -32,7 +34,8 @@ │ │ │ @ StatementsNode (location: (4,7)-(4,8)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (4,7)-(4,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: (4,9)-(4,12) = "end" │ └── end_keyword_loc: (4,9)-(4,12) = "end" ├── @ UnlessNode (location: (6,0)-(6,13)) @@ -44,7 +47,8 @@ │ │ @ StatementsNode (location: (6,0)-(6,1)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (6,0)-(6,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: ∅ │ └── end_keyword_loc: ∅ ├── @ UnlessNode (location: (8,0)-(8,17)) diff --git a/test/prism/snapshots/unparser/corpus/literal/assignment.txt b/test/prism/snapshots/unparser/corpus/literal/assignment.txt index 281a7ea515a2d5..3a458b83e80e39 100644 --- a/test/prism/snapshots/unparser/corpus/literal/assignment.txt +++ b/test/prism/snapshots/unparser/corpus/literal/assignment.txt @@ -8,7 +8,8 @@ │ ├── name_loc: (1,0)-(1,2) = "$a" │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,3)-(1,4) = "=" ├── @ MultiWriteNode (location: (2,0)-(2,17)) │ ├── lefts: (length: 2) @@ -26,9 +27,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (2,12)-(2,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (2,15)-(2,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (2,11)-(2,12) = "[" │ └── closing_loc: (2,16)-(2,17) = "]" ├── @ MultiWriteNode (location: (3,0)-(3,13)) @@ -53,7 +56,8 @@ │ ├── operator_loc: (3,10)-(3,11) = "=" │ └── value: │ @ IntegerNode (location: (3,12)-(3,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ MultiWriteNode (location: (4,0)-(4,9)) │ ├── lefts: (length: 0) │ ├── rest: @@ -91,9 +95,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (5,10)-(5,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (5,13)-(5,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (5,9)-(5,10) = "[" │ └── closing_loc: (5,14)-(5,15) = "]" ├── @ MultiWriteNode (location: (6,0)-(6,19)) @@ -112,9 +118,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (6,14)-(6,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (6,17)-(6,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (6,13)-(6,14) = "[" │ └── closing_loc: (6,18)-(6,19) = "]" ├── @ MultiWriteNode (location: (7,0)-(7,17)) @@ -133,9 +141,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (7,12)-(7,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (7,15)-(7,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (7,11)-(7,12) = "[" │ └── closing_loc: (7,16)-(7,17) = "]" ├── @ MultiWriteNode (location: (8,0)-(8,25)) @@ -165,14 +175,17 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (8,15)-(8,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ ArrayNode (location: (8,18)-(8,24)) │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (8,19)-(8,20)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (8,22)-(8,23)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (8,18)-(8,19) = "[" │ │ └── closing_loc: (8,23)-(8,24) = "]" │ ├── opening_loc: (8,14)-(8,15) = "[" @@ -195,9 +208,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (9,10)-(9,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (9,13)-(9,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (9,9)-(9,10) = "[" │ └── closing_loc: (9,14)-(9,15) = "]" ├── @ MultiWriteNode (location: (10,0)-(10,18)) @@ -221,9 +236,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (10,13)-(10,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (10,16)-(10,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (10,12)-(10,13) = "[" │ └── closing_loc: (10,17)-(10,18) = "]" ├── @ MultiWriteNode (location: (11,0)-(11,15)) @@ -244,9 +261,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (11,10)-(11,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (11,13)-(11,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (11,9)-(11,10) = "[" │ └── closing_loc: (11,14)-(11,15) = "]" ├── @ MultiWriteNode (location: (12,0)-(12,12)) @@ -311,9 +330,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (14,18)-(14,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (14,21)-(14,22)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (14,17)-(14,18) = "[" │ └── closing_loc: (14,22)-(14,23) = "]" ├── @ MultiWriteNode (location: (15,0)-(15,24)) @@ -349,7 +370,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (15,12)-(15,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (15,13)-(15,14) = "]" │ │ └── block: ∅ │ ├── rest: ∅ @@ -362,9 +384,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (15,19)-(15,20)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (15,22)-(15,23)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (15,18)-(15,19) = "[" │ └── closing_loc: (15,23)-(15,24) = "]" ├── @ MultiWriteNode (location: (16,0)-(16,21)) @@ -381,7 +405,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (16,3)-(16,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ ├── closing_loc: (16,4)-(16,5) = "]" │ │ │ └── block: ∅ │ │ └── @ IndexTargetNode (location: (16,7)-(16,11)) @@ -396,7 +421,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (16,9)-(16,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: (16,10)-(16,11) = "]" │ │ └── block: ∅ │ ├── rest: ∅ @@ -409,9 +435,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (16,16)-(16,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (16,19)-(16,20)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (16,15)-(16,16) = "[" │ └── closing_loc: (16,20)-(16,21) = "]" ├── @ MultiWriteNode (location: (17,0)-(17,12)) @@ -435,7 +463,8 @@ │ ├── operator_loc: (17,9)-(17,10) = "=" │ └── value: │ @ IntegerNode (location: (17,11)-(17,12)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ConstantPathWriteNode (location: (18,0)-(18,13)) │ ├── target: │ │ @ ConstantPathNode (location: (18,0)-(18,5)) @@ -457,21 +486,24 @@ │ ├── name_loc: (19,0)-(19,3) = "@@a" │ ├── value: │ │ @ IntegerNode (location: (19,6)-(19,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (19,4)-(19,5) = "=" ├── @ InstanceVariableWriteNode (location: (20,0)-(20,6)) │ ├── name: :@a │ ├── name_loc: (20,0)-(20,2) = "@a" │ ├── value: │ │ @ IntegerNode (location: (20,5)-(20,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (20,3)-(20,4) = "=" ├── @ ConstantWriteNode (location: (21,0)-(21,9)) │ ├── name: :CONST │ ├── name_loc: (21,0)-(21,5) = "CONST" │ ├── value: │ │ @ IntegerNode (location: (21,8)-(21,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (21,6)-(21,7) = "=" ├── @ ConstantPathWriteNode (location: (22,0)-(22,23)) │ ├── target: @@ -492,7 +524,8 @@ │ ├── operator_loc: (22,20)-(22,21) = "=" │ └── value: │ @ IntegerNode (location: (22,22)-(22,23)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ LocalVariableWriteNode (location: (23,0)-(23,16)) │ ├── name: :a │ ├── depth: 0 @@ -517,7 +550,8 @@ │ │ │ ├── operator_loc: (23,12)-(23,13) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (23,14)-(23,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (23,4)-(23,5) = "(" │ │ └── closing_loc: (23,15)-(23,16) = ")" │ └── operator_loc: (23,2)-(23,3) = "=" @@ -527,7 +561,8 @@ │ ├── name_loc: (24,0)-(24,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (24,4)-(24,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (24,2)-(24,3) = "=" ├── @ LocalVariableWriteNode (location: (25,0)-(25,11)) │ ├── name: :foo @@ -573,9 +608,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (27,8)-(27,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (27,11)-(27,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: (27,12)-(27,13) = ")" │ └── block: ∅ ├── @ CallNode (location: (28,0)-(28,11)) @@ -652,10 +689,12 @@ │ │ │ ├── flags: ∅ │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (30,4)-(30,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (30,7)-(30,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (30,5)-(30,7) = ".." │ │ └── @ CallNode (location: (30,12)-(30,17)) │ │ ├── flags: variable_call, ignore_visibility @@ -684,7 +723,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,8)-(31,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (31,4)-(31,5) = "]" │ └── block: ∅ ├── @ CallNode (location: (32,0)-(32,17)) diff --git a/test/prism/snapshots/unparser/corpus/literal/block.txt b/test/prism/snapshots/unparser/corpus/literal/block.txt index b7c571158f84e8..b4c86d0b04be45 100644 --- a/test/prism/snapshots/unparser/corpus/literal/block.txt +++ b/test/prism/snapshots/unparser/corpus/literal/block.txt @@ -167,7 +167,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,4)-(11,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (11,5)-(11,6) = ")" │ └── block: │ @ BlockNode (location: (11,7)-(13,1)) diff --git a/test/prism/snapshots/unparser/corpus/literal/case.txt b/test/prism/snapshots/unparser/corpus/literal/case.txt index d9990e59234198..84339d9f767e29 100644 --- a/test/prism/snapshots/unparser/corpus/literal/case.txt +++ b/test/prism/snapshots/unparser/corpus/literal/case.txt @@ -425,7 +425,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (36,14)-(36,15)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ └── statements: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/control.txt b/test/prism/snapshots/unparser/corpus/literal/control.txt index 3f667bd431fc74..9bb303fed42ca9 100644 --- a/test/prism/snapshots/unparser/corpus/literal/control.txt +++ b/test/prism/snapshots/unparser/corpus/literal/control.txt @@ -21,7 +21,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (6,7)-(6,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ReturnNode (location: (7,0)-(7,11)) │ ├── keyword_loc: (7,0)-(7,6) = "return" │ └── arguments: @@ -29,9 +30,11 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (7,7)-(7,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (7,10)-(7,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ ReturnNode (location: (8,0)-(8,19)) │ ├── keyword_loc: (8,0)-(8,6) = "return" │ └── arguments: @@ -47,7 +50,8 @@ │ │ @ StatementsNode (location: (8,14)-(8,15)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,14)-(8,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: │ │ @ ElseNode (location: (8,16)-(8,19)) │ │ ├── else_keyword_loc: (8,16)-(8,17) = ":" @@ -55,7 +59,8 @@ │ │ │ @ StatementsNode (location: (8,18)-(8,19)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (8,18)-(8,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: ∅ │ └── end_keyword_loc: ∅ ├── @ BreakNode (location: (9,0)-(9,18)) @@ -72,7 +77,8 @@ │ │ │ @ StatementsNode (location: (9,13)-(9,14)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (9,13)-(9,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── consequent: │ │ │ @ ElseNode (location: (9,15)-(9,18)) │ │ │ ├── else_keyword_loc: (9,15)-(9,16) = ":" @@ -80,7 +86,8 @@ │ │ │ │ @ StatementsNode (location: (9,17)-(9,18)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (9,17)-(9,18)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── end_keyword_loc: ∅ │ │ └── end_keyword_loc: ∅ │ └── keyword_loc: (9,0)-(9,5) = "break" @@ -98,7 +105,8 @@ │ │ │ @ StatementsNode (location: (10,12)-(10,13)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (10,12)-(10,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── consequent: │ │ │ @ ElseNode (location: (10,14)-(10,17)) │ │ │ ├── else_keyword_loc: (10,14)-(10,15) = ":" @@ -106,7 +114,8 @@ │ │ │ │ @ StatementsNode (location: (10,16)-(10,17)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (10,16)-(10,17)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── end_keyword_loc: ∅ │ │ └── end_keyword_loc: ∅ │ └── keyword_loc: (10,0)-(10,4) = "next" @@ -126,7 +135,8 @@ │ @ StatementsNode (location: (12,2)-(12,3)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (12,2)-(12,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── consequent: │ @ ElseNode (location: (13,0)-(15,3)) │ ├── else_keyword_loc: (13,0)-(13,4) = "else" @@ -134,6 +144,7 @@ │ │ @ StatementsNode (location: (14,2)-(14,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (14,2)-(14,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── end_keyword_loc: (15,0)-(15,3) = "end" └── end_keyword_loc: (15,0)-(15,3) = "end" diff --git a/test/prism/snapshots/unparser/corpus/literal/def.txt b/test/prism/snapshots/unparser/corpus/literal/def.txt index c8c571a1a704d5..da285d894ba5a5 100644 --- a/test/prism/snapshots/unparser/corpus/literal/def.txt +++ b/test/prism/snapshots/unparser/corpus/literal/def.txt @@ -643,7 +643,8 @@ │ │ │ ├── name_loc: (74,8)-(74,12) = "bar:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (74,13)-(74,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/defined.txt b/test/prism/snapshots/unparser/corpus/literal/defined.txt index f2a19370e5a567..89145ddcda8d30 100644 --- a/test/prism/snapshots/unparser/corpus/literal/defined.txt +++ b/test/prism/snapshots/unparser/corpus/literal/defined.txt @@ -42,9 +42,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (3,20)-(3,21)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (3,23)-(3,24)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (3,19)-(3,20) = "[" │ │ └── closing_loc: (3,24)-(3,25) = "]" │ ├── opening_loc: (3,9)-(3,10) = "(" diff --git a/test/prism/snapshots/unparser/corpus/literal/defs.txt b/test/prism/snapshots/unparser/corpus/literal/defs.txt index c3c9acbbca817b..431843cc1917ed 100644 --- a/test/prism/snapshots/unparser/corpus/literal/defs.txt +++ b/test/prism/snapshots/unparser/corpus/literal/defs.txt @@ -185,7 +185,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (22,9)-(22,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: (22,10)-(22,11) = ")" │ │ │ └── block: ∅ │ │ ├── opening_loc: (22,4)-(22,5) = "(" diff --git a/test/prism/snapshots/unparser/corpus/literal/dstr.txt b/test/prism/snapshots/unparser/corpus/literal/dstr.txt index cc3bfa4b31371e..2f8e5da65aecdd 100644 --- a/test/prism/snapshots/unparser/corpus/literal/dstr.txt +++ b/test/prism/snapshots/unparser/corpus/literal/dstr.txt @@ -215,7 +215,8 @@ │ │ │ │ │ @ StatementsNode (location: (28,6)-(28,8)) │ │ │ │ │ └── body: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (28,6)-(28,8)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 42 │ │ │ │ └── closing_loc: (28,8)-(28,9) = "}" │ │ │ └── @ StringNode (location: (28,9)-(29,0)) │ │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/flipflop.txt b/test/prism/snapshots/unparser/corpus/literal/flipflop.txt index 5e61e64da134a0..2794e0534f22a8 100644 --- a/test/prism/snapshots/unparser/corpus/literal/flipflop.txt +++ b/test/prism/snapshots/unparser/corpus/literal/flipflop.txt @@ -39,7 +39,8 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── opening_loc: (1,4)-(1,5) = "(" @@ -71,7 +72,8 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (1,20)-(1,21)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 4 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── opening_loc: (1,14)-(1,15) = "(" @@ -131,7 +133,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (4,10)-(4,11)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 4 │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── opening_loc: (4,4)-(4,5) = "(" @@ -163,7 +166,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (4,21)-(4,22)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 4 │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── opening_loc: (4,15)-(4,16) = "(" diff --git a/test/prism/snapshots/unparser/corpus/literal/if.txt b/test/prism/snapshots/unparser/corpus/literal/if.txt index fbbda9b930dd37..6a78779dc9ca2b 100644 --- a/test/prism/snapshots/unparser/corpus/literal/if.txt +++ b/test/prism/snapshots/unparser/corpus/literal/if.txt @@ -32,26 +32,30 @@ │ ├── if_keyword_loc: (4,0)-(4,2) = "if" │ ├── predicate: │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (5,2)-(5,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,2)-(5,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 9 │ ├── consequent: ∅ │ └── end_keyword_loc: (6,0)-(6,3) = "end" ├── @ IfNode (location: (7,0)-(11,3)) │ ├── if_keyword_loc: (7,0)-(7,2) = "if" │ ├── predicate: │ │ @ IntegerNode (location: (7,3)-(7,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (8,2)-(8,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (8,2)-(8,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 5 │ ├── consequent: │ │ @ ElseNode (location: (9,0)-(11,3)) │ │ ├── else_keyword_loc: (9,0)-(9,4) = "else" @@ -59,14 +63,16 @@ │ │ │ @ StatementsNode (location: (10,2)-(10,3)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (10,2)-(10,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 6 │ │ └── end_keyword_loc: (11,0)-(11,3) = "end" │ └── end_keyword_loc: (11,0)-(11,3) = "end" ├── @ UnlessNode (location: (12,0)-(14,3)) │ ├── keyword_loc: (12,0)-(12,6) = "unless" │ ├── predicate: │ │ @ IntegerNode (location: (12,7)-(12,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (13,2)-(13,5)) @@ -78,13 +84,15 @@ │ ├── keyword_loc: (15,0)-(15,6) = "unless" │ ├── predicate: │ │ @ IntegerNode (location: (15,7)-(15,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── then_keyword_loc: ∅ │ ├── statements: │ │ @ StatementsNode (location: (16,2)-(16,3)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (16,2)-(16,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 9 │ ├── consequent: ∅ │ └── end_keyword_loc: (17,0)-(17,3) = "end" ├── @ IfNode (location: (18,0)-(19,3)) diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt index e4545d16887ca9..6a3d817a6e401f 100644 --- a/test/prism/snapshots/unparser/corpus/literal/literal.txt +++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt @@ -290,12 +290,14 @@ │ │ └── name: :$a │ └── closing_loc: (14,13)-(14,14) = "\"" ├── @ IntegerNode (location: (15,0)-(15,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── @ CallNode (location: (16,0)-(16,3)) │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (16,1)-(16,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :+@ │ ├── message_loc: (16,0)-(16,1) = "+" @@ -304,13 +306,16 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ IntegerNode (location: (17,0)-(17,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ IntegerNode (location: (18,0)-(18,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ RationalNode (location: (19,0)-(19,2)) │ └── numeric: │ @ IntegerNode (location: (19,0)-(19,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ RationalNode (location: (20,0)-(20,4)) │ └── numeric: │ @ FloatNode (location: (20,0)-(20,3)) @@ -320,11 +325,13 @@ ├── @ ImaginaryNode (location: (22,0)-(22,2)) │ └── numeric: │ @ IntegerNode (location: (22,0)-(22,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 5 ├── @ ImaginaryNode (location: (23,0)-(23,3)) │ └── numeric: │ @ IntegerNode (location: (23,0)-(23,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -5 ├── @ ImaginaryNode (location: (24,0)-(24,4)) │ └── numeric: │ @ FloatNode (location: (24,0)-(24,3)) @@ -334,13 +341,15 @@ ├── @ ImaginaryNode (location: (26,0)-(26,32)) │ └── numeric: │ @ IntegerNode (location: (26,0)-(26,31)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1000000000000000000000000000000 ├── @ ImaginaryNode (location: (27,0)-(27,3)) │ └── numeric: │ @ RationalNode (location: (27,0)-(27,2)) │ └── numeric: │ @ IntegerNode (location: (27,0)-(27,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ InterpolatedStringNode (location: (28,0)-(28,11)) │ ├── opening_loc: ∅ │ ├── parts: (length: 2) @@ -398,7 +407,8 @@ │ │ │ │ @ StatementsNode (location: (30,6)-(30,7)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (30,6)-(30,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (30,7)-(30,8) = "}" │ │ └── @ StringNode (location: (30,8)-(30,11)) │ │ ├── flags: ∅ @@ -716,13 +726,15 @@ │ │ └── closing_loc: (60,10)-(60,11) = ")" │ ├── right: │ │ @ IntegerNode (location: (60,13)-(60,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (60,11)-(60,13) = ".." ├── @ RangeNode (location: (61,0)-(61,14)) │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (61,0)-(61,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ ParenthesesNode (location: (61,3)-(61,14)) │ │ ├── body: @@ -772,7 +784,8 @@ │ │ └── closing_loc: (62,10)-(62,11) = ")" │ ├── right: │ │ @ IntegerNode (location: (62,13)-(62,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 100 │ └── operator_loc: (62,11)-(62,13) = ".." ├── @ FloatNode (location: (63,0)-(63,4)) ├── @ FloatNode (location: (64,0)-(64,3)) @@ -780,16 +793,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (65,1)-(65,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (65,4)-(65,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (65,0)-(65,1) = "[" │ └── closing_loc: (65,5)-(65,6) = "]" ├── @ ArrayNode (location: (66,0)-(66,11)) │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (66,1)-(66,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ ParenthesesNode (location: (66,4)-(66,6)) │ │ │ ├── body: ∅ │ │ │ ├── opening_loc: (66,4)-(66,5) = "(" @@ -810,7 +826,8 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ IntegerNode (location: (67,1)-(67,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (67,0)-(67,1) = "[" │ └── closing_loc: (67,2)-(67,3) = "]" ├── @ ArrayNode (location: (68,0)-(68,2)) @@ -822,7 +839,8 @@ │ ├── flags: contains_splat │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (69,1)-(69,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ SplatNode (location: (69,4)-(69,9)) │ │ ├── operator_loc: (69,4)-(69,5) = "*" │ │ └── expression: @@ -839,7 +857,8 @@ │ │ │ @ InstanceVariableReadNode (location: (70,2)-(70,6)) │ │ │ └── name: :@foo │ │ └── @ IntegerNode (location: (70,8)-(70,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (70,0)-(70,1) = "[" │ └── closing_loc: (70,9)-(70,10) = "]" ├── @ ArrayNode (location: (71,0)-(71,14)) @@ -883,10 +902,12 @@ │ │ └── @ AssocNode (location: (74,2)-(74,8)) │ │ ├── key: │ │ │ @ IntegerNode (location: (74,2)-(74,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (74,7)-(74,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (74,4)-(74,6) = "=>" │ └── closing_loc: (74,9)-(74,10) = "}" ├── @ HashNode (location: (75,0)-(75,18)) @@ -895,18 +916,22 @@ │ │ ├── @ AssocNode (location: (75,2)-(75,8)) │ │ │ ├── key: │ │ │ │ @ IntegerNode (location: (75,2)-(75,3)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (75,7)-(75,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (75,4)-(75,6) = "=>" │ │ └── @ AssocNode (location: (75,10)-(75,16)) │ │ ├── key: │ │ │ @ IntegerNode (location: (75,10)-(75,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── value: │ │ │ @ IntegerNode (location: (75,15)-(75,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 4 │ │ └── operator_loc: (75,12)-(75,14) = "=>" │ └── closing_loc: (75,17)-(75,18) = "}" ├── @ HashNode (location: (76,0)-(76,27)) @@ -928,7 +953,8 @@ │ │ │ │ │ └── @ RescueModifierNode (location: (76,6)-(76,18)) │ │ │ │ │ ├── expression: │ │ │ │ │ │ @ IntegerNode (location: (76,6)-(76,7)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ ├── keyword_loc: (76,8)-(76,14) = "rescue" │ │ │ │ │ └── rescue_expression: │ │ │ │ │ @ CallNode (location: (76,15)-(76,18)) @@ -954,7 +980,8 @@ │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (76,24)-(76,25)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (76,26)-(76,27) = "}" ├── @ HashNode (location: (77,0)-(77,14)) @@ -970,7 +997,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (77,5)-(77,6)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ └── @ AssocNode (location: (77,8)-(77,12)) │ │ ├── key: @@ -982,7 +1010,8 @@ │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (77,11)-(77,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (77,13)-(77,14) = "}" ├── @ HashNode (location: (78,0)-(78,9)) @@ -1018,7 +1047,8 @@ │ │ │ └── unescaped: "a b" │ │ ├── value: │ │ │ @ IntegerNode (location: (79,12)-(79,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (79,9)-(79,11) = "=>" │ └── closing_loc: (79,14)-(79,15) = "}" ├── @ HashNode (location: (80,0)-(80,12)) @@ -1034,7 +1064,8 @@ │ │ │ └── unescaped: "-@" │ │ ├── value: │ │ │ @ IntegerNode (location: (80,9)-(80,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (80,6)-(80,8) = "=>" │ └── closing_loc: (80,11)-(80,12) = "}" ├── @ InterpolatedStringNode (location: (81,0)-(82,7)) diff --git a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt index d4efe8de6b99e4..8dc084963819b9 100644 --- a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt +++ b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt @@ -8,7 +8,8 @@ │ ├── operator_loc: (1,2)-(1,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ ├── operator: :+ │ └── depth: 0 @@ -17,7 +18,8 @@ │ ├── operator_loc: (2,2)-(2,4) = "-=" │ ├── value: │ │ @ IntegerNode (location: (2,5)-(2,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ ├── operator: :- │ └── depth: 0 @@ -26,7 +28,8 @@ │ ├── operator_loc: (3,2)-(3,5) = "**=" │ ├── value: │ │ @ IntegerNode (location: (3,6)-(3,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ ├── operator: :** │ └── depth: 0 @@ -35,7 +38,8 @@ │ ├── operator_loc: (4,2)-(4,4) = "*=" │ ├── value: │ │ @ IntegerNode (location: (4,5)-(4,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ ├── operator: :* │ └── depth: 0 @@ -44,7 +48,8 @@ │ ├── operator_loc: (5,2)-(5,4) = "/=" │ ├── value: │ │ @ IntegerNode (location: (5,5)-(5,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ ├── operator: :/ │ └── depth: 0 @@ -69,7 +74,8 @@ │ ├── operator_loc: (7,2)-(7,5) = "||=" │ ├── value: │ │ @ IntegerNode (location: (7,6)-(7,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── name: :a │ └── depth: 0 ├── @ CallNode (location: (8,0)-(8,13)) @@ -84,7 +90,8 @@ │ │ │ ├── operator_loc: (8,3)-(8,6) = "||=" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (8,7)-(8,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── opening_loc: (8,0)-(8,1) = "(" @@ -159,7 +166,8 @@ │ ├── operator_loc: (10,4)-(10,6) = "+=" │ └── value: │ @ IntegerNode (location: (10,7)-(10,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ CallOperatorWriteNode (location: (11,0)-(11,8)) │ ├── flags: ∅ │ ├── receiver: @@ -174,7 +182,8 @@ │ ├── operator_loc: (11,4)-(11,6) = "-=" │ └── value: │ @ IntegerNode (location: (11,7)-(11,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ CallOperatorWriteNode (location: (12,0)-(12,9)) │ ├── flags: ∅ │ ├── receiver: @@ -189,7 +198,8 @@ │ ├── operator_loc: (12,4)-(12,7) = "**=" │ └── value: │ @ IntegerNode (location: (12,8)-(12,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ CallOperatorWriteNode (location: (13,0)-(13,8)) │ ├── flags: ∅ │ ├── receiver: @@ -204,7 +214,8 @@ │ ├── operator_loc: (13,4)-(13,6) = "*=" │ └── value: │ @ IntegerNode (location: (13,7)-(13,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ CallOperatorWriteNode (location: (14,0)-(14,8)) │ ├── flags: ∅ │ ├── receiver: @@ -219,7 +230,8 @@ │ ├── operator_loc: (14,4)-(14,6) = "/=" │ └── value: │ @ IntegerNode (location: (14,7)-(14,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ CallAndWriteNode (location: (15,0)-(15,9)) │ ├── flags: ∅ │ ├── receiver: @@ -255,7 +267,8 @@ │ ├── operator_loc: (16,4)-(16,7) = "||=" │ └── value: │ @ IntegerNode (location: (16,8)-(16,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (17,0)-(17,9)) │ ├── flags: ∅ │ ├── receiver: @@ -284,7 +297,8 @@ │ ├── operator_loc: (17,5)-(17,7) = "+=" │ └── value: │ @ IntegerNode (location: (17,8)-(17,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (18,0)-(18,9)) │ ├── flags: ∅ │ ├── receiver: @@ -313,7 +327,8 @@ │ ├── operator_loc: (18,5)-(18,7) = "-=" │ └── value: │ @ IntegerNode (location: (18,8)-(18,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (19,0)-(19,10)) │ ├── flags: ∅ │ ├── receiver: @@ -342,7 +357,8 @@ │ ├── operator_loc: (19,5)-(19,8) = "**=" │ └── value: │ @ IntegerNode (location: (19,9)-(19,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (20,0)-(20,9)) │ ├── flags: ∅ │ ├── receiver: @@ -371,7 +387,8 @@ │ ├── operator_loc: (20,5)-(20,7) = "*=" │ └── value: │ @ IntegerNode (location: (20,8)-(20,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexOperatorWriteNode (location: (21,0)-(21,9)) │ ├── flags: ∅ │ ├── receiver: @@ -400,7 +417,8 @@ │ ├── operator_loc: (21,5)-(21,7) = "/=" │ └── value: │ @ IntegerNode (location: (21,8)-(21,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── @ IndexAndWriteNode (location: (22,0)-(22,10)) │ ├── flags: ∅ │ ├── receiver: @@ -464,7 +482,8 @@ │ ├── operator_loc: (23,5)-(23,8) = "||=" │ └── value: │ @ IntegerNode (location: (23,9)-(23,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── @ CallOperatorWriteNode (location: (24,0)-(24,10)) ├── flags: ∅ ├── receiver: @@ -486,4 +505,5 @@ ├── operator_loc: (24,6)-(24,8) = "+=" └── value: @ IntegerNode (location: (24,9)-(24,10)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/unparser/corpus/literal/pattern.txt b/test/prism/snapshots/unparser/corpus/literal/pattern.txt index d89ef39c90b06c..5a0b4bb7336399 100644 --- a/test/prism/snapshots/unparser/corpus/literal/pattern.txt +++ b/test/prism/snapshots/unparser/corpus/literal/pattern.txt @@ -24,9 +24,11 @@ │ │ │ │ │ └── name: :A │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ IntegerNode (location: (2,5)-(2,6)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ IntegerNode (location: (2,8)-(2,9)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 2 │ │ │ │ ├── rest: │ │ │ │ │ @ SplatNode (location: (2,11)-(2,13)) │ │ │ │ │ ├── operator_loc: (2,11)-(2,12) = "*" @@ -36,7 +38,8 @@ │ │ │ │ │ └── depth: 0 │ │ │ │ ├── posts: (length: 1) │ │ │ │ │ └── @ IntegerNode (location: (2,15)-(2,16)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 3 │ │ │ │ ├── opening_loc: (2,4)-(2,5) = "[" │ │ │ │ └── closing_loc: (2,16)-(2,17) = "]" │ │ │ ├── statements: @@ -51,9 +54,11 @@ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ IntegerNode (location: (4,4)-(4,5)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── @ IntegerNode (location: (4,7)-(4,8)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 2 │ │ │ │ ├── rest: │ │ │ │ │ @ ImplicitRestNode (location: (4,8)-(4,9)) │ │ │ │ ├── posts: (length: 0) @@ -188,7 +193,8 @@ │ │ │ │ │ │ │ └── unescaped: "a" │ │ │ │ │ │ ├── value: │ │ │ │ │ │ │ @ IntegerNode (location: (14,7)-(14,8)) - │ │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ │ └── value: 1 │ │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ │ └── @ AssocNode (location: (14,10)-(14,15)) │ │ │ │ │ ├── key: @@ -200,7 +206,8 @@ │ │ │ │ │ │ └── unescaped: "aa" │ │ │ │ │ ├── value: │ │ │ │ │ │ @ IntegerNode (location: (14,14)-(14,15)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 2 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ │ │ │ │ ├── opening_loc: (14,3)-(14,4) = "{" @@ -257,7 +264,8 @@ │ │ │ │ │ │ └── unescaped: "a" │ │ │ │ │ ├── value: │ │ │ │ │ │ @ IntegerNode (location: (20,9)-(20,10)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ │ │ │ │ ├── opening_loc: (20,3)-(20,4) = "{" @@ -273,10 +281,12 @@ │ │ │ │ @ AlternationPatternNode (location: (22,3)-(22,8)) │ │ │ │ ├── left: │ │ │ │ │ @ IntegerNode (location: (22,3)-(22,4)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── right: │ │ │ │ │ @ IntegerNode (location: (22,7)-(22,8)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 2 │ │ │ │ └── operator_loc: (22,5)-(22,6) = "|" │ │ │ ├── statements: │ │ │ │ @ StatementsNode (location: (23,2)-(23,6)) @@ -289,7 +299,8 @@ │ │ │ │ @ CapturePatternNode (location: (24,3)-(24,9)) │ │ │ │ ├── value: │ │ │ │ │ @ IntegerNode (location: (24,3)-(24,4)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── target: │ │ │ │ │ @ LocalVariableTargetNode (location: (24,8)-(24,9)) │ │ │ │ │ ├── name: :a @@ -318,14 +329,16 @@ │ │ ├── @ InNode (location: (28,0)-(28,4)) │ │ │ ├── pattern: │ │ │ │ @ IntegerNode (location: (28,3)-(28,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── statements: ∅ │ │ │ ├── in_loc: (28,0)-(28,2) = "in" │ │ │ └── then_loc: ∅ │ │ └── @ InNode (location: (29,0)-(30,6)) │ │ ├── pattern: │ │ │ @ IntegerNode (location: (29,3)-(29,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── statements: │ │ │ @ StatementsNode (location: (30,2)-(30,6)) │ │ │ └── body: (length: 1) @@ -363,9 +376,11 @@ │ │ │ │ └── name: :A │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (35,5)-(35,6)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── @ IntegerNode (location: (35,8)-(35,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (35,11)-(35,13)) │ │ │ │ ├── operator_loc: (35,11)-(35,12) = "*" @@ -375,7 +390,8 @@ │ │ │ │ └── depth: 0 │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ IntegerNode (location: (35,15)-(35,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 3 │ │ │ ├── opening_loc: (35,4)-(35,5) = "[" │ │ │ └── closing_loc: (35,16)-(35,17) = "]" │ │ ├── statements: ∅ @@ -414,7 +430,8 @@ └── @ MatchPredicateNode (location: (41,0)-(41,8)) ├── value: │ @ IntegerNode (location: (41,0)-(41,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── pattern: │ @ ArrayPatternNode (location: (41,5)-(41,8)) │ ├── constant: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/range.txt b/test/prism/snapshots/unparser/corpus/literal/range.txt index 5bf208d9624c7a..ab015d04fce0e2 100644 --- a/test/prism/snapshots/unparser/corpus/literal/range.txt +++ b/test/prism/snapshots/unparser/corpus/literal/range.txt @@ -11,7 +11,8 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (1,2)-(1,4) = ".." │ ├── opening_loc: (1,0)-(1,1) = "(" @@ -20,10 +21,12 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: (2,1)-(2,3) = ".." ├── @ ParenthesesNode (location: (3,0)-(3,6)) │ ├── body: @@ -33,7 +36,8 @@ │ │ ├── flags: exclude_end │ │ ├── left: │ │ │ @ IntegerNode (location: (3,1)-(3,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── right: ∅ │ │ └── operator_loc: (3,2)-(3,5) = "..." │ ├── opening_loc: (3,0)-(3,1) = "(" @@ -42,8 +46,10 @@ ├── flags: exclude_end ├── left: │ @ IntegerNode (location: (4,0)-(4,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── right: │ @ IntegerNode (location: (4,4)-(4,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (4,1)-(4,4) = "..." diff --git a/test/prism/snapshots/unparser/corpus/literal/send.txt b/test/prism/snapshots/unparser/corpus/literal/send.txt index 18608ca0057842..25de1f4865ad21 100644 --- a/test/prism/snapshots/unparser/corpus/literal/send.txt +++ b/test/prism/snapshots/unparser/corpus/literal/send.txt @@ -65,7 +65,8 @@ │ │ │ ├── name_loc: (6,2)-(6,7) = "local" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (6,10)-(6,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: (6,8)-(6,9) = "=" │ │ └── @ CallNode (location: (7,2)-(7,11)) │ │ ├── flags: ∅ @@ -463,10 +464,12 @@ │ │ │ ├── flags: ∅ │ │ │ ├── left: │ │ │ │ @ IntegerNode (location: (38,1)-(38,2)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── right: │ │ │ │ @ IntegerNode (location: (38,4)-(38,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── operator_loc: (38,2)-(38,4) = ".." │ │ ├── opening_loc: (38,0)-(38,1) = "(" │ │ └── closing_loc: (38,5)-(38,6) = ")" @@ -580,13 +583,15 @@ │ ├── flags: ∅ │ ├── left: │ │ @ IntegerNode (location: (42,0)-(42,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── right: │ │ @ CallNode (location: (42,3)-(42,8)) │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (42,3)-(42,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── call_operator_loc: (42,4)-(42,5) = "." │ │ ├── name: :max │ │ ├── message_loc: (42,5)-(42,8) = "max" @@ -901,9 +906,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (54,4)-(54,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (54,7)-(54,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: (54,8)-(54,9) = ")" │ └── block: ∅ ├── @ CallNode (location: (55,0)-(55,8)) @@ -1732,9 +1739,11 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ IntegerNode (location: (74,4)-(74,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (74,7)-(74,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── closing_loc: (74,8)-(74,9) = "]" │ └── block: ∅ ├── @ CallNode (location: (75,0)-(75,5)) diff --git a/test/prism/snapshots/unparser/corpus/literal/since/27.txt b/test/prism/snapshots/unparser/corpus/literal/since/27.txt index 64f3fd88b37138..60edc18604f026 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/27.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/27.txt @@ -42,7 +42,8 @@ │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (4,1)-(4,3) = ".." ├── opening_loc: (4,0)-(4,1) = "(" └── closing_loc: (4,4)-(4,5) = ")" diff --git a/test/prism/snapshots/unparser/corpus/literal/since/30.txt b/test/prism/snapshots/unparser/corpus/literal/since/30.txt index f595ebb7804c40..300dd869f5a59a 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/30.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/30.txt @@ -6,7 +6,8 @@ ├── @ MatchRequiredNode (location: (1,0)-(1,8)) │ ├── value: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (1,5)-(1,8)) │ │ ├── constant: ∅ @@ -22,7 +23,8 @@ ├── @ MatchRequiredNode (location: (2,0)-(2,8)) │ ├── value: │ │ @ IntegerNode (location: (2,0)-(2,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (2,5)-(2,8)) │ │ ├── constant: ∅ @@ -38,7 +40,8 @@ ├── @ MatchPredicateNode (location: (3,0)-(3,15)) │ ├── value: │ │ @ IntegerNode (location: (3,0)-(3,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── pattern: │ │ @ FindPatternNode (location: (3,5)-(3,15)) │ │ ├── constant: ∅ @@ -48,7 +51,8 @@ │ │ │ └── expression: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ IntegerNode (location: (3,9)-(3,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── right: │ │ │ @ SplatNode (location: (3,13)-(3,14)) │ │ │ ├── operator_loc: (3,13)-(3,14) = "*" @@ -59,7 +63,8 @@ └── @ MatchPredicateNode (location: (4,0)-(4,17)) ├── value: │ @ IntegerNode (location: (4,0)-(4,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── pattern: │ @ FindPatternNode (location: (4,5)-(4,17)) │ ├── constant: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/unary.txt b/test/prism/snapshots/unparser/corpus/literal/unary.txt index a5a314a6205942..5e9563d811d5b7 100644 --- a/test/prism/snapshots/unparser/corpus/literal/unary.txt +++ b/test/prism/snapshots/unparser/corpus/literal/unary.txt @@ -7,7 +7,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: ∅ │ ├── name: :! │ ├── message_loc: (1,0)-(1,1) = "!" @@ -26,7 +27,8 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ IntegerNode (location: (2,3)-(2,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :! │ │ │ ├── message_loc: (2,2)-(2,3) = "!" @@ -113,7 +115,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: │ │ │ │ │ @ IntegerNode (location: (4,3)-(4,4)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :! │ │ │ │ ├── message_loc: (4,2)-(4,3) = "!" diff --git a/test/prism/snapshots/unparser/corpus/literal/while.txt b/test/prism/snapshots/unparser/corpus/literal/while.txt index 67cd69db0356ea..0f752f3392ddb3 100644 --- a/test/prism/snapshots/unparser/corpus/literal/while.txt +++ b/test/prism/snapshots/unparser/corpus/literal/while.txt @@ -609,7 +609,8 @@ │ @ StatementsNode (location: (59,2)-(59,3)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (59,2)-(59,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── @ WhileNode (location: (61,0)-(64,3)) │ ├── flags: ∅ │ ├── keyword_loc: (61,0)-(61,5) = "while" @@ -663,7 +664,8 @@ │ @ StatementsNode (location: (68,2)-(68,3)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (68,2)-(68,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 └── @ UntilNode (location: (70,0)-(73,3)) ├── flags: ∅ ├── keyword_loc: (70,0)-(70,5) = "until" diff --git a/test/prism/snapshots/unparser/corpus/semantic/literal.txt b/test/prism/snapshots/unparser/corpus/semantic/literal.txt index 5854765fadc51e..915254d3728d95 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/literal.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/literal.txt @@ -9,11 +9,14 @@ ├── @ RationalNode (location: (2,0)-(2,3)) │ └── numeric: │ @ IntegerNode (location: (2,0)-(2,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── @ IntegerNode (location: (3,0)-(3,3)) - │ └── flags: hexadecimal + │ ├── flags: hexadecimal + │ └── value: 1 ├── @ IntegerNode (location: (4,0)-(4,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1000 ├── @ FloatNode (location: (5,0)-(5,4)) ├── @ FloatNode (location: (6,0)-(6,14)) ├── @ FloatNode (location: (7,0)-(7,15)) diff --git a/test/prism/snapshots/unparser/corpus/semantic/send.txt b/test/prism/snapshots/unparser/corpus/semantic/send.txt index a4e261e37785a1..7c152c3bfbe00a 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/send.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/send.txt @@ -25,7 +25,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (2,4)-(2,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (2,5)-(2,6) = ")" │ └── block: ∅ ├── @ CallNode (location: (4,0)-(4,15)) diff --git a/test/prism/snapshots/until.txt b/test/prism/snapshots/until.txt index bb3987a0455548..fc7cb92c91a0be 100644 --- a/test/prism/snapshots/until.txt +++ b/test/prism/snapshots/until.txt @@ -13,7 +13,8 @@ │ @ StatementsNode (location: (1,12)-(1,13)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ UntilNode (location: (3,0)-(3,12)) │ ├── flags: ∅ │ ├── keyword_loc: (3,2)-(3,7) = "until" @@ -24,7 +25,8 @@ │ @ StatementsNode (location: (3,0)-(3,1)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (3,0)-(3,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ UntilNode (location: (5,0)-(5,16)) │ ├── flags: ∅ │ ├── keyword_loc: (5,6)-(5,11) = "until" diff --git a/test/prism/snapshots/variables.txt b/test/prism/snapshots/variables.txt index 37cd4556f0845b..b79612f924feff 100644 --- a/test/prism/snapshots/variables.txt +++ b/test/prism/snapshots/variables.txt @@ -10,7 +10,8 @@ │ ├── name_loc: (3,0)-(3,5) = "@@abc" │ ├── value: │ │ @ IntegerNode (location: (3,8)-(3,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (3,6)-(3,7) = "=" ├── @ MultiWriteNode (location: (5,0)-(5,16)) │ ├── lefts: (length: 2) @@ -25,7 +26,8 @@ │ ├── operator_loc: (5,13)-(5,14) = "=" │ └── value: │ @ IntegerNode (location: (5,15)-(5,16)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ ClassVariableWriteNode (location: (7,0)-(7,12)) │ ├── name: :@@foo │ ├── name_loc: (7,0)-(7,5) = "@@foo" @@ -34,9 +36,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (7,8)-(7,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (7,11)-(7,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (7,6)-(7,7) = "=" @@ -45,7 +49,8 @@ │ ├── name_loc: (9,0)-(9,4) = "$abc" │ ├── value: │ │ @ IntegerNode (location: (9,7)-(9,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (9,5)-(9,6) = "=" ├── @ GlobalVariableReadNode (location: (11,0)-(11,4)) │ └── name: :$abc @@ -56,7 +61,8 @@ │ ├── name_loc: (15,0)-(15,4) = "@abc" │ ├── value: │ │ @ IntegerNode (location: (15,7)-(15,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (15,5)-(15,6) = "=" ├── @ CallNode (location: (17,0)-(17,1)) │ ├── flags: variable_call, ignore_visibility @@ -74,7 +80,8 @@ │ ├── name_loc: (19,0)-(19,3) = "abc" │ ├── value: │ │ @ IntegerNode (location: (19,6)-(19,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (19,4)-(19,5) = "=" ├── @ MultiWriteNode (location: (21,0)-(21,14)) │ ├── lefts: (length: 2) @@ -89,7 +96,8 @@ │ ├── operator_loc: (21,11)-(21,12) = "=" │ └── value: │ @ IntegerNode (location: (21,13)-(21,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ GlobalVariableWriteNode (location: (23,0)-(23,11)) │ ├── name: :$foo │ ├── name_loc: (23,0)-(23,4) = "$foo" @@ -98,9 +106,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (23,7)-(23,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (23,10)-(23,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (23,5)-(23,6) = "=" @@ -117,7 +127,8 @@ │ ├── operator_loc: (25,11)-(25,12) = "=" │ └── value: │ @ IntegerNode (location: (25,13)-(25,14)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ InstanceVariableWriteNode (location: (27,0)-(27,11)) │ ├── name: :@foo │ ├── name_loc: (27,0)-(27,4) = "@foo" @@ -126,9 +137,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (27,7)-(27,8)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (27,10)-(27,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (27,5)-(27,6) = "=" @@ -138,7 +151,8 @@ │ ├── name_loc: (29,0)-(29,3) = "foo" │ ├── value: │ │ @ IntegerNode (location: (29,6)-(29,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (29,4)-(29,5) = "=" ├── @ LocalVariableWriteNode (location: (29,9)-(29,19)) │ ├── name: :foo @@ -149,9 +163,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (29,15)-(29,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (29,18)-(29,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (29,13)-(29,14) = "=" @@ -164,9 +180,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (31,6)-(31,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (31,9)-(31,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (31,4)-(31,5) = "=" @@ -188,9 +206,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (33,9)-(33,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (33,12)-(33,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ MultiWriteNode (location: (35,0)-(35,11)) @@ -209,9 +229,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (35,7)-(35,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (35,10)-(35,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ MultiWriteNode (location: (37,0)-(37,16)) @@ -235,9 +257,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (37,12)-(37,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (37,15)-(37,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ MultiWriteNode (location: (39,0)-(39,27)) @@ -267,14 +291,17 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (39,18)-(39,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ ArrayNode (location: (39,21)-(39,27)) │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (39,22)-(39,23)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ └── @ IntegerNode (location: (39,25)-(39,26)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 3 │ │ ├── opening_loc: (39,21)-(39,22) = "[" │ │ └── closing_loc: (39,26)-(39,27) = "]" │ ├── opening_loc: ∅ @@ -304,9 +331,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (43,6)-(43,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (43,9)-(43,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (43,4)-(43,5) = "=" diff --git a/test/prism/snapshots/while.txt b/test/prism/snapshots/while.txt index 3599bc4bb8c74c..9f191647984458 100644 --- a/test/prism/snapshots/while.txt +++ b/test/prism/snapshots/while.txt @@ -13,7 +13,8 @@ │ @ StatementsNode (location: (1,12)-(1,13)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ WhileNode (location: (3,0)-(3,12)) │ ├── flags: ∅ │ ├── keyword_loc: (3,2)-(3,7) = "while" @@ -24,7 +25,8 @@ │ @ StatementsNode (location: (3,0)-(3,1)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (3,0)-(3,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ WhileNode (location: (5,0)-(5,16)) │ ├── flags: ∅ │ ├── keyword_loc: (5,6)-(5,11) = "while" diff --git a/test/prism/snapshots/whitequark/and_asgn.txt b/test/prism/snapshots/whitequark/and_asgn.txt index af4b86cead69f1..5c7a9a23191e09 100644 --- a/test/prism/snapshots/whitequark/and_asgn.txt +++ b/test/prism/snapshots/whitequark/and_asgn.txt @@ -23,7 +23,8 @@ │ ├── operator_loc: (1,6)-(1,9) = "&&=" │ └── value: │ @ IntegerNode (location: (1,10)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ IndexAndWriteNode (location: (3,0)-(3,15)) ├── flags: ∅ ├── receiver: @@ -44,12 +45,15 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (3,4)-(3,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ └── @ IntegerNode (location: (3,7)-(3,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (3,8)-(3,9) = "]" ├── block: ∅ ├── operator_loc: (3,10)-(3,13) = "&&=" └── value: @ IntegerNode (location: (3,14)-(3,15)) - └── flags: decimal + ├── flags: decimal + └── value: 2 diff --git a/test/prism/snapshots/whitequark/args.txt b/test/prism/snapshots/whitequark/args.txt index 3468650956582c..bc7ea8ad7dbf62 100644 --- a/test/prism/snapshots/whitequark/args.txt +++ b/test/prism/snapshots/whitequark/args.txt @@ -391,7 +391,8 @@ │ │ │ ├── name_loc: (23,7)-(23,11) = "foo:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (23,12)-(23,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (23,15)-(23,17)) @@ -424,14 +425,16 @@ │ │ │ │ ├── name_loc: (25,7)-(25,11) = "foo:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (25,12)-(25,13)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ OptionalKeywordParameterNode (location: (25,15)-(25,21)) │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (25,15)-(25,19) = "bar:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (25,20)-(25,21)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (25,23)-(25,28)) │ │ │ ├── flags: ∅ @@ -710,7 +713,8 @@ │ │ │ ├── operator_loc: (43,10)-(43,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (43,11)-(43,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -747,7 +751,8 @@ │ │ │ ├── operator_loc: (45,10)-(45,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (45,11)-(45,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (45,14)-(45,16)) │ │ │ ├── flags: ∅ @@ -789,7 +794,8 @@ │ │ │ ├── operator_loc: (47,10)-(47,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (47,11)-(47,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (47,14)-(47,16)) │ │ │ ├── flags: ∅ @@ -834,7 +840,8 @@ │ │ │ ├── operator_loc: (49,10)-(49,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (49,11)-(49,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (49,14)-(49,15)) @@ -898,7 +905,8 @@ │ │ │ ├── name_loc: (54,6)-(54,10) = "foo:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (54,11)-(54,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: -1 │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ @@ -924,7 +932,8 @@ │ │ │ ├── operator_loc: (57,7)-(57,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (57,8)-(57,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -958,7 +967,8 @@ │ │ │ ├── operator_loc: (59,7)-(59,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (59,8)-(59,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (59,11)-(59,13)) │ │ │ ├── flags: ∅ @@ -997,7 +1007,8 @@ │ │ │ ├── operator_loc: (61,7)-(61,8) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (61,8)-(61,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: │ │ │ @ RestParameterNode (location: (61,11)-(61,13)) │ │ │ ├── flags: ∅ @@ -1039,7 +1050,8 @@ │ │ ├── operator_loc: (63,7)-(63,8) = "=" │ │ └── value: │ │ @ IntegerNode (location: (63,8)-(63,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── rest: ∅ │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (63,11)-(63,12)) diff --git a/test/prism/snapshots/whitequark/args_args_assocs.txt b/test/prism/snapshots/whitequark/args_args_assocs.txt index 3520b0e67275ac..6297f212d8e651 100644 --- a/test/prism/snapshots/whitequark/args_args_assocs.txt +++ b/test/prism/snapshots/whitequark/args_args_assocs.txt @@ -37,7 +37,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,17)-(1,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,14)-(1,16) = "=>" │ ├── closing_loc: (1,18)-(1,19) = ")" │ └── block: ∅ @@ -75,7 +76,8 @@ │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (3,17)-(3,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (3,14)-(3,16) = "=>" ├── closing_loc: (3,24)-(3,25) = ")" └── block: diff --git a/test/prism/snapshots/whitequark/args_args_assocs_comma.txt b/test/prism/snapshots/whitequark/args_args_assocs_comma.txt index 3e9f0a8f9fc39c..969514a5112146 100644 --- a/test/prism/snapshots/whitequark/args_args_assocs_comma.txt +++ b/test/prism/snapshots/whitequark/args_args_assocs_comma.txt @@ -47,7 +47,8 @@ │ │ └── unescaped: "baz" │ ├── value: │ │ @ IntegerNode (location: (1,17)-(1,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,14)-(1,16) = "=>" ├── closing_loc: (1,19)-(1,20) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/args_assocs.txt b/test/prism/snapshots/whitequark/args_assocs.txt index 6d8bd6b1bddbce..47cb68d899bf99 100644 --- a/test/prism/snapshots/whitequark/args_assocs.txt +++ b/test/prism/snapshots/whitequark/args_assocs.txt @@ -27,7 +27,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,9)-(1,11) = "=>" │ ├── closing_loc: (1,13)-(1,14) = ")" │ └── block: ∅ @@ -55,7 +56,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,12)-(3,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (3,9)-(3,11) = "=>" │ ├── closing_loc: (3,19)-(3,20) = ")" │ └── block: @@ -107,7 +109,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,20)-(5,21)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (5,17)-(5,19) = "=>" │ ├── closing_loc: ∅ │ └── block: ∅ @@ -136,7 +139,8 @@ │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ IntegerNode (location: (7,13)-(7,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (7,10)-(7,12) = "=>" │ ├── closing_loc: (7,14)-(7,15) = "]" │ └── block: ∅ @@ -160,7 +164,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (9,14)-(9,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── operator_loc: (9,11)-(9,13) = "=>" │ ├── rparen_loc: (9,16)-(9,17) = ")" │ └── block: ∅ @@ -184,6 +189,7 @@ │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (11,14)-(11,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ └── operator_loc: (11,11)-(11,13) = "=>" └── rparen_loc: (11,16)-(11,17) = ")" diff --git a/test/prism/snapshots/whitequark/args_assocs_comma.txt b/test/prism/snapshots/whitequark/args_assocs_comma.txt index bea6e8b3006d47..b1b9fbeefebc8b 100644 --- a/test/prism/snapshots/whitequark/args_assocs_comma.txt +++ b/test/prism/snapshots/whitequark/args_assocs_comma.txt @@ -37,7 +37,8 @@ │ │ └── unescaped: "baz" │ ├── value: │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,9)-(1,11) = "=>" ├── closing_loc: (1,14)-(1,15) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/args_assocs_legacy.txt b/test/prism/snapshots/whitequark/args_assocs_legacy.txt index 6d8bd6b1bddbce..47cb68d899bf99 100644 --- a/test/prism/snapshots/whitequark/args_assocs_legacy.txt +++ b/test/prism/snapshots/whitequark/args_assocs_legacy.txt @@ -27,7 +27,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (1,9)-(1,11) = "=>" │ ├── closing_loc: (1,13)-(1,14) = ")" │ └── block: ∅ @@ -55,7 +56,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,12)-(3,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (3,9)-(3,11) = "=>" │ ├── closing_loc: (3,19)-(3,20) = ")" │ └── block: @@ -107,7 +109,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,20)-(5,21)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (5,17)-(5,19) = "=>" │ ├── closing_loc: ∅ │ └── block: ∅ @@ -136,7 +139,8 @@ │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ IntegerNode (location: (7,13)-(7,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: (7,10)-(7,12) = "=>" │ ├── closing_loc: (7,14)-(7,15) = "]" │ └── block: ∅ @@ -160,7 +164,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (9,14)-(9,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── operator_loc: (9,11)-(9,13) = "=>" │ ├── rparen_loc: (9,16)-(9,17) = ")" │ └── block: ∅ @@ -184,6 +189,7 @@ │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (11,14)-(11,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ └── operator_loc: (11,11)-(11,13) = "=>" └── rparen_loc: (11,16)-(11,17) = ")" diff --git a/test/prism/snapshots/whitequark/array_assocs.txt b/test/prism/snapshots/whitequark/array_assocs.txt index c66356b89ae7de..3747e3f7d843e7 100644 --- a/test/prism/snapshots/whitequark/array_assocs.txt +++ b/test/prism/snapshots/whitequark/array_assocs.txt @@ -12,10 +12,12 @@ │ │ └── @ AssocNode (location: (1,2)-(1,8)) │ │ ├── key: │ │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (1,4)-(1,6) = "=>" │ ├── opening_loc: (1,0)-(1,1) = "[" │ └── closing_loc: (1,9)-(1,10) = "]" @@ -23,17 +25,20 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (3,2)-(3,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ KeywordHashNode (location: (3,5)-(3,11)) │ ├── flags: ∅ │ └── elements: (length: 1) │ └── @ AssocNode (location: (3,5)-(3,11)) │ ├── key: │ │ @ IntegerNode (location: (3,5)-(3,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── value: │ │ @ IntegerNode (location: (3,10)-(3,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ └── operator_loc: (3,7)-(3,9) = "=>" ├── opening_loc: (3,0)-(3,1) = "[" └── closing_loc: (3,12)-(3,13) = "]" diff --git a/test/prism/snapshots/whitequark/array_plain.txt b/test/prism/snapshots/whitequark/array_plain.txt index 17dd4a2137e1de..b183a7ac6bbdfe 100644 --- a/test/prism/snapshots/whitequark/array_plain.txt +++ b/test/prism/snapshots/whitequark/array_plain.txt @@ -7,8 +7,10 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: (1,0)-(1,1) = "[" └── closing_loc: (1,5)-(1,6) = "]" diff --git a/test/prism/snapshots/whitequark/array_splat.txt b/test/prism/snapshots/whitequark/array_splat.txt index fd1ce43f8deea7..f76563e9f48952 100644 --- a/test/prism/snapshots/whitequark/array_splat.txt +++ b/test/prism/snapshots/whitequark/array_splat.txt @@ -25,7 +25,8 @@ │ ├── flags: contains_splat │ ├── elements: (length: 3) │ │ ├── @ IntegerNode (location: (3,1)-(3,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── @ SplatNode (location: (3,4)-(3,8)) │ │ │ ├── operator_loc: (3,4)-(3,5) = "*" │ │ │ └── expression: @@ -40,14 +41,16 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ IntegerNode (location: (3,10)-(3,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: (3,0)-(3,1) = "[" │ └── closing_loc: (3,11)-(3,12) = "]" └── @ ArrayNode (location: (5,0)-(5,9)) ├── flags: contains_splat ├── elements: (length: 2) │ ├── @ IntegerNode (location: (5,1)-(5,2)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ SplatNode (location: (5,4)-(5,8)) │ ├── operator_loc: (5,4)-(5,5) = "*" │ └── expression: diff --git a/test/prism/snapshots/whitequark/asgn_mrhs.txt b/test/prism/snapshots/whitequark/asgn_mrhs.txt index a5811faf919bc7..41d5bdc5bff968 100644 --- a/test/prism/snapshots/whitequark/asgn_mrhs.txt +++ b/test/prism/snapshots/whitequark/asgn_mrhs.txt @@ -46,7 +46,8 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── @ IntegerNode (location: (3,11)-(3,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: ∅ │ │ └── closing_loc: ∅ │ └── operator_loc: (3,4)-(3,5) = "=" diff --git a/test/prism/snapshots/whitequark/begin_cmdarg.txt b/test/prism/snapshots/whitequark/begin_cmdarg.txt index 975f664c865e86..b0c03c1754463c 100644 --- a/test/prism/snapshots/whitequark/begin_cmdarg.txt +++ b/test/prism/snapshots/whitequark/begin_cmdarg.txt @@ -23,7 +23,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── call_operator_loc: (1,9)-(1,10) = "." │ │ ├── name: :times │ │ ├── message_loc: (1,10)-(1,15) = "times" @@ -38,7 +39,8 @@ │ │ │ @ StatementsNode (location: (1,19)-(1,20)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,19)-(1,20)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (1,16)-(1,18) = "do" │ │ └── closing_loc: (1,21)-(1,24) = "end" │ ├── rescue_clause: ∅ diff --git a/test/prism/snapshots/whitequark/beginless_erange_after_newline.txt b/test/prism/snapshots/whitequark/beginless_erange_after_newline.txt index bffa01e42ad4ae..69db24a12733c2 100644 --- a/test/prism/snapshots/whitequark/beginless_erange_after_newline.txt +++ b/test/prism/snapshots/whitequark/beginless_erange_after_newline.txt @@ -18,5 +18,6 @@ ├── left: ∅ ├── right: │ @ IntegerNode (location: (2,3)-(2,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 100 └── operator_loc: (2,0)-(2,3) = "..." diff --git a/test/prism/snapshots/whitequark/beginless_irange_after_newline.txt b/test/prism/snapshots/whitequark/beginless_irange_after_newline.txt index b0fb7258a78bc5..cbc11c83c13aba 100644 --- a/test/prism/snapshots/whitequark/beginless_irange_after_newline.txt +++ b/test/prism/snapshots/whitequark/beginless_irange_after_newline.txt @@ -18,5 +18,6 @@ ├── left: ∅ ├── right: │ @ IntegerNode (location: (2,2)-(2,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 100 └── operator_loc: (2,0)-(2,2) = ".." diff --git a/test/prism/snapshots/whitequark/beginless_range.txt b/test/prism/snapshots/whitequark/beginless_range.txt index ffbde4de345b4d..59e6f135add5fa 100644 --- a/test/prism/snapshots/whitequark/beginless_range.txt +++ b/test/prism/snapshots/whitequark/beginless_range.txt @@ -8,12 +8,14 @@ │ ├── left: ∅ │ ├── right: │ │ @ IntegerNode (location: (1,3)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 100 │ └── operator_loc: (1,0)-(1,3) = "..." └── @ RangeNode (location: (3,0)-(3,5)) ├── flags: ∅ ├── left: ∅ ├── right: │ @ IntegerNode (location: (3,2)-(3,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 100 └── operator_loc: (3,0)-(3,2) = ".." diff --git a/test/prism/snapshots/whitequark/blockargs.txt b/test/prism/snapshots/whitequark/blockargs.txt index fc229453a86c2a..149c3765c948c1 100644 --- a/test/prism/snapshots/whitequark/blockargs.txt +++ b/test/prism/snapshots/whitequark/blockargs.txt @@ -688,7 +688,8 @@ │ │ │ │ ├── operator_loc: (41,8)-(41,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (41,9)-(41,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 0) @@ -733,7 +734,8 @@ │ │ │ │ ├── operator_loc: (43,8)-(43,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (43,9)-(43,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (43,12)-(43,14)) │ │ │ │ ├── flags: ∅ @@ -786,7 +788,8 @@ │ │ │ │ │ ├── operator_loc: (45,8)-(45,9) = "=" │ │ │ │ │ └── value: │ │ │ │ │ @ IntegerNode (location: (45,9)-(45,10)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── @ OptionalParameterNode (location: (45,12)-(45,16)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o1 @@ -794,7 +797,8 @@ │ │ │ │ ├── operator_loc: (45,14)-(45,15) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (45,15)-(45,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (45,18)-(45,20)) │ │ │ │ ├── flags: ∅ @@ -844,7 +848,8 @@ │ │ │ │ ├── operator_loc: (47,8)-(47,9) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (47,9)-(47,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (47,12)-(47,13)) @@ -1020,7 +1025,8 @@ │ │ │ │ ├── name_loc: (57,4)-(57,8) = "foo:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (57,9)-(57,10)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (57,12)-(57,14)) @@ -1061,14 +1067,16 @@ │ │ │ │ │ ├── name_loc: (59,4)-(59,8) = "foo:" │ │ │ │ │ └── value: │ │ │ │ │ @ IntegerNode (location: (59,9)-(59,10)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 │ │ │ │ └── @ OptionalKeywordParameterNode (location: (59,12)-(59,18)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ ├── name_loc: (59,12)-(59,16) = "bar:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (59,17)-(59,18)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 │ │ │ ├── keyword_rest: │ │ │ │ @ KeywordRestParameterNode (location: (59,20)-(59,25)) │ │ │ │ ├── flags: ∅ @@ -1145,7 +1153,8 @@ │ │ │ │ ├── operator_loc: (63,5)-(63,6) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (63,6)-(63,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 0) @@ -1187,7 +1196,8 @@ │ │ │ │ ├── operator_loc: (65,5)-(65,6) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (65,6)-(65,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (65,9)-(65,11)) │ │ │ │ ├── flags: ∅ @@ -1234,7 +1244,8 @@ │ │ │ │ ├── operator_loc: (67,5)-(67,6) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (67,6)-(67,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (67,9)-(67,11)) │ │ │ │ ├── flags: ∅ @@ -1284,7 +1295,8 @@ │ │ │ │ ├── operator_loc: (69,5)-(69,6) = "=" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (69,6)-(69,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (69,9)-(69,10)) diff --git a/test/prism/snapshots/whitequark/bug_447.txt b/test/prism/snapshots/whitequark/bug_447.txt index 5b01cc8a1888ea..7291d011751019 100644 --- a/test/prism/snapshots/whitequark/bug_447.txt +++ b/test/prism/snapshots/whitequark/bug_447.txt @@ -44,7 +44,8 @@ │ │ ├── opening_loc: (3,2)-(3,3) = "[" │ │ └── closing_loc: (3,3)-(3,4) = "]" │ └── @ IntegerNode (location: (3,6)-(3,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: @ BlockNode (location: (3,8)-(3,14)) diff --git a/test/prism/snapshots/whitequark/bug_452.txt b/test/prism/snapshots/whitequark/bug_452.txt index 7410184788d189..e1ea52fbd13b86 100644 --- a/test/prism/snapshots/whitequark/bug_452.txt +++ b/test/prism/snapshots/whitequark/bug_452.txt @@ -22,7 +22,8 @@ │ │ │ │ @ StatementsNode (location: (1,4)-(1,9)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,4)-(1,9)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1500 │ │ │ ├── opening_loc: (1,3)-(1,4) = "(" │ │ │ └── closing_loc: (1,9)-(1,10) = ")" │ │ ├── call_operator_loc: (1,10)-(1,11) = "." diff --git a/test/prism/snapshots/whitequark/bug_466.txt b/test/prism/snapshots/whitequark/bug_466.txt index a0be5655a19ccf..3f65dee04873be 100644 --- a/test/prism/snapshots/whitequark/bug_466.txt +++ b/test/prism/snapshots/whitequark/bug_466.txt @@ -33,7 +33,8 @@ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── receiver: │ │ │ │ │ │ @ IntegerNode (location: (1,8)-(1,9)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :+ │ │ │ │ │ ├── message_loc: (1,9)-(1,10) = "+" @@ -43,7 +44,8 @@ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── arguments: (length: 1) │ │ │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ │ │ └── flags: decimal + │ │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ │ └── value: 1 │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── opening_loc: (1,7)-(1,8) = "(" diff --git a/test/prism/snapshots/whitequark/bug_481.txt b/test/prism/snapshots/whitequark/bug_481.txt index f0166388e81ff4..0b093d483c0fc8 100644 --- a/test/prism/snapshots/whitequark/bug_481.txt +++ b/test/prism/snapshots/whitequark/bug_481.txt @@ -33,7 +33,8 @@ ├── flags: ∅ ├── receiver: │ @ IntegerNode (location: (1,16)-(1,17)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── call_operator_loc: (1,17)-(1,18) = "." ├── name: :tap ├── message_loc: (1,18)-(1,21) = "tap" diff --git a/test/prism/snapshots/whitequark/bug_interp_single.txt b/test/prism/snapshots/whitequark/bug_interp_single.txt index 699dd6297e86d9..6a9d56b519ed03 100644 --- a/test/prism/snapshots/whitequark/bug_interp_single.txt +++ b/test/prism/snapshots/whitequark/bug_interp_single.txt @@ -12,7 +12,8 @@ │ │ │ @ StatementsNode (location: (1,3)-(1,4)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── closing_loc: (1,4)-(1,5) = "}" │ └── closing_loc: (1,5)-(1,6) = "\"" └── @ ArrayNode (location: (3,0)-(3,8)) @@ -27,7 +28,8 @@ │ │ │ @ StatementsNode (location: (3,5)-(3,6)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,5)-(3,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── closing_loc: (3,6)-(3,7) = "}" │ └── closing_loc: ∅ ├── opening_loc: (3,0)-(3,3) = "%W\"" diff --git a/test/prism/snapshots/whitequark/casgn_scoped.txt b/test/prism/snapshots/whitequark/casgn_scoped.txt index bb3a8b072a2e0b..4e3fd6fe4461c9 100644 --- a/test/prism/snapshots/whitequark/casgn_scoped.txt +++ b/test/prism/snapshots/whitequark/casgn_scoped.txt @@ -16,4 +16,5 @@ ├── operator_loc: (1,9)-(1,10) = "=" └── value: @ IntegerNode (location: (1,11)-(1,13)) - └── flags: decimal + ├── flags: decimal + └── value: 10 diff --git a/test/prism/snapshots/whitequark/casgn_toplevel.txt b/test/prism/snapshots/whitequark/casgn_toplevel.txt index bc48b1e84139dc..11facfefb36284 100644 --- a/test/prism/snapshots/whitequark/casgn_toplevel.txt +++ b/test/prism/snapshots/whitequark/casgn_toplevel.txt @@ -14,4 +14,5 @@ ├── operator_loc: (1,6)-(1,7) = "=" └── value: @ IntegerNode (location: (1,8)-(1,10)) - └── flags: decimal + ├── flags: decimal + └── value: 10 diff --git a/test/prism/snapshots/whitequark/casgn_unscoped.txt b/test/prism/snapshots/whitequark/casgn_unscoped.txt index 90434d39dbbf3e..f535cafdc6304b 100644 --- a/test/prism/snapshots/whitequark/casgn_unscoped.txt +++ b/test/prism/snapshots/whitequark/casgn_unscoped.txt @@ -8,5 +8,6 @@ ├── name_loc: (1,0)-(1,3) = "Foo" ├── value: │ @ IntegerNode (location: (1,6)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 10 └── operator_loc: (1,4)-(1,5) = "=" diff --git a/test/prism/snapshots/whitequark/complex.txt b/test/prism/snapshots/whitequark/complex.txt index f81564d7006d5d..80e7c00fb9d270 100644 --- a/test/prism/snapshots/whitequark/complex.txt +++ b/test/prism/snapshots/whitequark/complex.txt @@ -14,10 +14,12 @@ ├── @ ImaginaryNode (location: (5,0)-(5,3)) │ └── numeric: │ @ IntegerNode (location: (5,0)-(5,2)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 └── @ ImaginaryNode (location: (7,0)-(7,4)) └── numeric: @ RationalNode (location: (7,0)-(7,3)) └── numeric: @ IntegerNode (location: (7,0)-(7,2)) - └── flags: decimal + ├── flags: decimal + └── value: 42 diff --git a/test/prism/snapshots/whitequark/const_op_asgn.txt b/test/prism/snapshots/whitequark/const_op_asgn.txt index fc6533ccd008ac..4985f3e54b9ced 100644 --- a/test/prism/snapshots/whitequark/const_op_asgn.txt +++ b/test/prism/snapshots/whitequark/const_op_asgn.txt @@ -14,7 +14,8 @@ │ ├── operator_loc: (1,4)-(1,6) = "+=" │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator: :+ ├── @ ConstantOperatorWriteNode (location: (3,0)-(3,6)) │ ├── name: :A @@ -22,7 +23,8 @@ │ ├── operator_loc: (3,2)-(3,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (3,5)-(3,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator: :+ ├── @ ConstantPathOperatorWriteNode (location: (5,0)-(5,9)) │ ├── target: @@ -37,7 +39,8 @@ │ ├── operator_loc: (5,5)-(5,7) = "+=" │ ├── value: │ │ @ IntegerNode (location: (5,8)-(5,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator: :+ ├── @ DefNode (location: (7,0)-(7,21)) │ ├── name: :x @@ -58,7 +61,8 @@ │ │ ├── operator_loc: (7,11)-(7,14) = "||=" │ │ └── value: │ │ @ IntegerNode (location: (7,15)-(7,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── locals: [] │ ├── def_keyword_loc: (7,0)-(7,3) = "def" │ ├── operator_loc: ∅ @@ -86,7 +90,8 @@ │ ├── operator_loc: (9,15)-(9,18) = "||=" │ └── value: │ @ IntegerNode (location: (9,19)-(9,20)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── locals: [] ├── def_keyword_loc: (9,0)-(9,3) = "def" ├── operator_loc: ∅ diff --git a/test/prism/snapshots/whitequark/cvasgn.txt b/test/prism/snapshots/whitequark/cvasgn.txt index e6a1c7e9737d9f..f3eceed4a47a35 100644 --- a/test/prism/snapshots/whitequark/cvasgn.txt +++ b/test/prism/snapshots/whitequark/cvasgn.txt @@ -8,5 +8,6 @@ ├── name_loc: (1,0)-(1,5) = "@@var" ├── value: │ @ IntegerNode (location: (1,8)-(1,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 10 └── operator_loc: (1,6)-(1,7) = "=" diff --git a/test/prism/snapshots/whitequark/endless_method.txt b/test/prism/snapshots/whitequark/endless_method.txt index d2443223bbc14c..17d3873b66381f 100644 --- a/test/prism/snapshots/whitequark/endless_method.txt +++ b/test/prism/snapshots/whitequark/endless_method.txt @@ -12,7 +12,8 @@ │ │ @ StatementsNode (location: (1,12)-(1,14)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,12)-(1,14)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" │ ├── operator_loc: ∅ @@ -54,7 +55,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,17)-(3,18)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [:x] @@ -83,7 +85,8 @@ │ │ @ StatementsNode (location: (5,16)-(5,18)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,16)-(5,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (5,0)-(5,3) = "def" │ ├── operator_loc: (5,7)-(5,8) = "." @@ -135,7 +138,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,21)-(7,22)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── locals: [:x] diff --git a/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt b/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt index 8f8e770fa973e3..2284b243549535 100644 --- a/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt +++ b/test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt @@ -14,11 +14,13 @@ │ │ └── @ RescueModifierNode (location: (1,10)-(1,20)) │ │ ├── expression: │ │ │ @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── keyword_loc: (1,12)-(1,18) = "rescue" │ │ └── rescue_expression: │ │ @ IntegerNode (location: (1,19)-(1,20)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" │ ├── operator_loc: ∅ @@ -38,11 +40,13 @@ │ └── @ RescueModifierNode (location: (3,15)-(3,25)) │ ├── expression: │ │ @ IntegerNode (location: (3,15)-(3,16)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_loc: (3,17)-(3,23) = "rescue" │ └── rescue_expression: │ @ IntegerNode (location: (3,24)-(3,25)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── locals: [] ├── def_keyword_loc: (3,0)-(3,3) = "def" ├── operator_loc: (3,8)-(3,9) = "." diff --git a/test/prism/snapshots/whitequark/endless_method_without_args.txt b/test/prism/snapshots/whitequark/endless_method_without_args.txt index b7db96171e6397..a7a9c93ef34dd4 100644 --- a/test/prism/snapshots/whitequark/endless_method_without_args.txt +++ b/test/prism/snapshots/whitequark/endless_method_without_args.txt @@ -12,7 +12,8 @@ │ │ @ StatementsNode (location: (1,10)-(1,12)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (1,0)-(1,3) = "def" │ ├── operator_loc: ∅ @@ -31,7 +32,8 @@ │ │ └── @ RescueModifierNode (location: (3,10)-(3,23)) │ │ ├── expression: │ │ │ @ IntegerNode (location: (3,10)-(3,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── keyword_loc: (3,13)-(3,19) = "rescue" │ │ └── rescue_expression: │ │ @ NilNode (location: (3,20)-(3,23)) @@ -52,7 +54,8 @@ │ │ @ StatementsNode (location: (5,15)-(5,17)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,15)-(5,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── locals: [] │ ├── def_keyword_loc: (5,0)-(5,3) = "def" │ ├── operator_loc: (5,8)-(5,9) = "." @@ -72,7 +75,8 @@ │ └── @ RescueModifierNode (location: (7,15)-(7,28)) │ ├── expression: │ │ @ IntegerNode (location: (7,15)-(7,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 42 │ ├── keyword_loc: (7,18)-(7,24) = "rescue" │ └── rescue_expression: │ @ NilNode (location: (7,25)-(7,28)) diff --git a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt index 90b49655435ac7..7e58260b582202 100644 --- a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt +++ b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt @@ -251,7 +251,8 @@ │ │ │ ├── operator_loc: (18,13)-(18,14) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (18,15)-(18,16)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -281,7 +282,8 @@ │ │ │ ├── operator_loc: (21,10)-(21,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (21,12)-(21,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -327,7 +329,8 @@ │ │ │ ├── operator_loc: (25,10)-(25,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (25,12)-(25,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/whitequark/gvasgn.txt b/test/prism/snapshots/whitequark/gvasgn.txt index 541a3a0fc4b23a..fc044054d8878a 100644 --- a/test/prism/snapshots/whitequark/gvasgn.txt +++ b/test/prism/snapshots/whitequark/gvasgn.txt @@ -8,5 +8,6 @@ ├── name_loc: (1,0)-(1,4) = "$var" ├── value: │ @ IntegerNode (location: (1,7)-(1,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 10 └── operator_loc: (1,5)-(1,6) = "=" diff --git a/test/prism/snapshots/whitequark/hash_hashrocket.txt b/test/prism/snapshots/whitequark/hash_hashrocket.txt index 124de2f3a3718c..e661a7b0480e8d 100644 --- a/test/prism/snapshots/whitequark/hash_hashrocket.txt +++ b/test/prism/snapshots/whitequark/hash_hashrocket.txt @@ -9,10 +9,12 @@ │ │ └── @ AssocNode (location: (1,2)-(1,8)) │ │ ├── key: │ │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (1,4)-(1,6) = "=>" │ └── closing_loc: (1,9)-(1,10) = "}" └── @ HashNode (location: (3,0)-(3,25)) @@ -21,10 +23,12 @@ │ ├── @ AssocNode (location: (3,2)-(3,8)) │ │ ├── key: │ │ │ @ IntegerNode (location: (3,2)-(3,3)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── value: │ │ │ @ IntegerNode (location: (3,7)-(3,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: (3,4)-(3,6) = "=>" │ └── @ AssocNode (location: (3,10)-(3,23)) │ ├── key: diff --git a/test/prism/snapshots/whitequark/hash_kwsplat.txt b/test/prism/snapshots/whitequark/hash_kwsplat.txt index b0d75a64b47124..a5d12174cc40d2 100644 --- a/test/prism/snapshots/whitequark/hash_kwsplat.txt +++ b/test/prism/snapshots/whitequark/hash_kwsplat.txt @@ -16,7 +16,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocSplatNode (location: (1,10)-(1,15)) │ ├── value: diff --git a/test/prism/snapshots/whitequark/hash_label.txt b/test/prism/snapshots/whitequark/hash_label.txt index bbc49bbbd7a59a..fdf7a21ed0ca5e 100644 --- a/test/prism/snapshots/whitequark/hash_label.txt +++ b/test/prism/snapshots/whitequark/hash_label.txt @@ -16,6 +16,7 @@ │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── operator_loc: ∅ └── closing_loc: (1,9)-(1,10) = "}" diff --git a/test/prism/snapshots/whitequark/hash_label_end.txt b/test/prism/snapshots/whitequark/hash_label_end.txt index 71fd7b00501e41..88b70d38e2cf05 100644 --- a/test/prism/snapshots/whitequark/hash_label_end.txt +++ b/test/prism/snapshots/whitequark/hash_label_end.txt @@ -44,7 +44,8 @@ │ │ │ │ @ StatementsNode (location: (1,10)-(1,11)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── end_keyword_loc: ∅ │ │ └── end_keyword_loc: ∅ │ ├── closing_loc: (1,11)-(1,12) = ")" @@ -62,7 +63,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,9)-(3,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── closing_loc: (3,11)-(3,12) = "}" └── @ HashNode (location: (5,0)-(5,22)) @@ -78,7 +80,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,9)-(5,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── operator_loc: ∅ │ └── @ AssocNode (location: (5,12)-(5,21)) │ ├── key: diff --git a/test/prism/snapshots/whitequark/if_elsif.txt b/test/prism/snapshots/whitequark/if_elsif.txt index aab6d4003bc2e9..1bd1ab7f426cfd 100644 --- a/test/prism/snapshots/whitequark/if_elsif.txt +++ b/test/prism/snapshots/whitequark/if_elsif.txt @@ -49,7 +49,8 @@ │ │ @ StatementsNode (location: (1,24)-(1,25)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,24)-(1,25)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── consequent: │ │ @ ElseNode (location: (1,27)-(1,38)) │ │ ├── else_keyword_loc: (1,27)-(1,31) = "else" @@ -57,7 +58,8 @@ │ │ │ @ StatementsNode (location: (1,32)-(1,33)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,32)-(1,33)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ └── end_keyword_loc: (1,35)-(1,38) = "end" │ └── end_keyword_loc: (1,35)-(1,38) = "end" └── end_keyword_loc: (1,35)-(1,38) = "end" diff --git a/test/prism/snapshots/whitequark/int.txt b/test/prism/snapshots/whitequark/int.txt index 8690dee172727d..6fee32f1175384 100644 --- a/test/prism/snapshots/whitequark/int.txt +++ b/test/prism/snapshots/whitequark/int.txt @@ -4,8 +4,11 @@ @ StatementsNode (location: (1,0)-(5,2)) └── body: (length: 3) ├── @ IntegerNode (location: (1,0)-(1,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 42 ├── @ IntegerNode (location: (3,0)-(3,3)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: -42 └── @ IntegerNode (location: (5,0)-(5,2)) - └── flags: decimal + ├── flags: decimal + └── value: 42 diff --git a/test/prism/snapshots/whitequark/ivasgn.txt b/test/prism/snapshots/whitequark/ivasgn.txt index 3be3907f629835..2b57f395541746 100644 --- a/test/prism/snapshots/whitequark/ivasgn.txt +++ b/test/prism/snapshots/whitequark/ivasgn.txt @@ -8,5 +8,6 @@ ├── name_loc: (1,0)-(1,4) = "@var" ├── value: │ @ IntegerNode (location: (1,7)-(1,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 10 └── operator_loc: (1,5)-(1,6) = "=" diff --git a/test/prism/snapshots/whitequark/kwoptarg.txt b/test/prism/snapshots/whitequark/kwoptarg.txt index cb4e6c39e7a585..9c2c4f9c4ce842 100644 --- a/test/prism/snapshots/whitequark/kwoptarg.txt +++ b/test/prism/snapshots/whitequark/kwoptarg.txt @@ -20,7 +20,8 @@ │ │ ├── name_loc: (1,6)-(1,10) = "foo:" │ │ └── value: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: ∅ diff --git a/test/prism/snapshots/whitequark/lvasgn.txt b/test/prism/snapshots/whitequark/lvasgn.txt index dfa7183840fd5e..be35c005875da4 100644 --- a/test/prism/snapshots/whitequark/lvasgn.txt +++ b/test/prism/snapshots/whitequark/lvasgn.txt @@ -9,7 +9,8 @@ │ ├── name_loc: (1,0)-(1,3) = "var" │ ├── value: │ │ @ IntegerNode (location: (1,6)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator_loc: (1,4)-(1,5) = "=" └── @ LocalVariableReadNode (location: (1,10)-(1,13)) ├── name: :var diff --git a/test/prism/snapshots/whitequark/masgn.txt b/test/prism/snapshots/whitequark/masgn.txt index d87d21a60538aa..32e46bfdf7a7ef 100644 --- a/test/prism/snapshots/whitequark/masgn.txt +++ b/test/prism/snapshots/whitequark/masgn.txt @@ -21,9 +21,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (1,13)-(1,14)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (1,16)-(1,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ ├── @ MultiWriteNode (location: (3,0)-(3,15)) @@ -44,9 +46,11 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ IntegerNode (location: (3,11)-(3,12)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ IntegerNode (location: (3,14)-(3,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── opening_loc: ∅ │ └── closing_loc: ∅ └── @ MultiWriteNode (location: (5,0)-(5,20)) @@ -70,8 +74,10 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (5,16)-(5,17)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (5,19)-(5,20)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: ∅ └── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/masgn_attr.txt b/test/prism/snapshots/whitequark/masgn_attr.txt index c77b54e096845f..f4f4276597f5ed 100644 --- a/test/prism/snapshots/whitequark/masgn_attr.txt +++ b/test/prism/snapshots/whitequark/masgn_attr.txt @@ -43,9 +43,11 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ IntegerNode (location: (3,13)-(3,14)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (3,16)-(3,17)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── closing_loc: (3,17)-(3,18) = "]" │ │ └── block: ∅ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt index c3479d139a7524..afa3517e116596 100644 --- a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt +++ b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt @@ -18,7 +18,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (1,5)-(1,6) = "}" │ ├── pattern: @@ -59,7 +60,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (2,4)-(2,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (2,5)-(2,6) = "}" │ ├── pattern: @@ -100,7 +102,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (4,4)-(4,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (4,5)-(4,6) = "}" │ ├── pattern: @@ -141,7 +144,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (5,4)-(5,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 0 │ │ └── operator_loc: ∅ │ └── closing_loc: (5,5)-(5,6) = "}" ├── pattern: diff --git a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt index a57e9f5b285ca1..d5e89d87f9c8df 100644 --- a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt +++ b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt @@ -43,7 +43,8 @@ │ │ │ │ @ StatementsNode (location: (3,0)-(4,4)) │ │ │ │ └── body: (length: 2) │ │ │ │ ├── @ IntegerNode (location: (3,0)-(3,1)) - │ │ │ │ │ └── flags: decimal + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 0 │ │ │ │ └── @ TrueNode (location: (4,0)-(4,4)) │ │ │ ├── in_loc: (2,0)-(2,2) = "in" │ │ │ └── then_loc: ∅ @@ -74,7 +75,8 @@ │ │ │ @ StatementsNode (location: (6,0)-(7,4)) │ │ │ └── body: (length: 2) │ │ │ ├── @ IntegerNode (location: (6,0)-(6,1)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 0 │ │ │ └── @ TrueNode (location: (7,0)-(7,4)) │ │ ├── in_loc: (5,0)-(5,2) = "in" │ │ └── then_loc: ∅ @@ -115,7 +117,8 @@ │ │ │ └── unescaped: "foo" │ │ ├── value: │ │ │ @ IntegerNode (location: (11,0)-(11,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ @@ -153,7 +156,8 @@ │ │ └── unescaped: "foo" │ ├── value: │ │ @ IntegerNode (location: (14,0)-(14,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: ∅ ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/non_lvar_injecting_match.txt b/test/prism/snapshots/whitequark/non_lvar_injecting_match.txt index 7b577e5bd9fd7c..2df571e8dc1890 100644 --- a/test/prism/snapshots/whitequark/non_lvar_injecting_match.txt +++ b/test/prism/snapshots/whitequark/non_lvar_injecting_match.txt @@ -16,7 +16,8 @@ │ │ │ │ @ StatementsNode (location: (1,3)-(1,4)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,3)-(1,4)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── closing_loc: (1,4)-(1,5) = "}" │ │ └── @ StringNode (location: (1,5)-(1,18)) │ │ ├── flags: ∅ diff --git a/test/prism/snapshots/whitequark/op_asgn.txt b/test/prism/snapshots/whitequark/op_asgn.txt index 5d7fb0c7fa86ba..8f24a35ad0d555 100644 --- a/test/prism/snapshots/whitequark/op_asgn.txt +++ b/test/prism/snapshots/whitequark/op_asgn.txt @@ -24,7 +24,8 @@ │ ├── operator_loc: (1,6)-(1,8) = "+=" │ └── value: │ @ IntegerNode (location: (1,9)-(1,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── @ CallOperatorWriteNode (location: (3,0)-(3,10)) │ ├── flags: ∅ │ ├── receiver: @@ -46,7 +47,8 @@ │ ├── operator_loc: (3,6)-(3,8) = "+=" │ └── value: │ @ IntegerNode (location: (3,9)-(3,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ CallOperatorWriteNode (location: (5,0)-(5,11)) ├── flags: ∅ ├── receiver: @@ -68,4 +70,5 @@ ├── operator_loc: (5,7)-(5,9) = "+=" └── value: @ IntegerNode (location: (5,10)-(5,11)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/whitequark/op_asgn_index.txt b/test/prism/snapshots/whitequark/op_asgn_index.txt index 8bce2fce3c4fcf..fe077fae13fe6c 100644 --- a/test/prism/snapshots/whitequark/op_asgn_index.txt +++ b/test/prism/snapshots/whitequark/op_asgn_index.txt @@ -23,13 +23,16 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,8)-(1,9) = "]" ├── block: ∅ ├── operator: :+ ├── operator_loc: (1,10)-(1,12) = "+=" └── value: @ IntegerNode (location: (1,13)-(1,14)) - └── flags: decimal + ├── flags: decimal + └── value: 2 diff --git a/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt b/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt index 389f0360053141..87082aad947c99 100644 --- a/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt +++ b/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt @@ -23,9 +23,11 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (1,8)-(1,9) = "]" ├── block: ∅ ├── operator: :+ diff --git a/test/prism/snapshots/whitequark/optarg.txt b/test/prism/snapshots/whitequark/optarg.txt index 15ac9e00ef1efb..695ed827ad5450 100644 --- a/test/prism/snapshots/whitequark/optarg.txt +++ b/test/prism/snapshots/whitequark/optarg.txt @@ -18,7 +18,8 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) @@ -47,7 +48,8 @@ │ │ │ ├── operator_loc: (3,9)-(3,10) = "=" │ │ │ └── value: │ │ │ @ IntegerNode (location: (3,10)-(3,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── @ OptionalParameterNode (location: (3,13)-(3,18)) │ │ ├── flags: ∅ │ │ ├── name: :bar @@ -55,7 +57,8 @@ │ │ ├── operator_loc: (3,16)-(3,17) = "=" │ │ └── value: │ │ @ IntegerNode (location: (3,17)-(3,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 0) diff --git a/test/prism/snapshots/whitequark/or_asgn.txt b/test/prism/snapshots/whitequark/or_asgn.txt index ccc14c45b4858b..c0ded24b933dbe 100644 --- a/test/prism/snapshots/whitequark/or_asgn.txt +++ b/test/prism/snapshots/whitequark/or_asgn.txt @@ -23,7 +23,8 @@ │ ├── operator_loc: (1,6)-(1,9) = "||=" │ └── value: │ @ IntegerNode (location: (1,10)-(1,11)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ IndexOrWriteNode (location: (3,0)-(3,15)) ├── flags: ∅ ├── receiver: @@ -44,12 +45,15 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (3,4)-(3,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ └── @ IntegerNode (location: (3,7)-(3,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (3,8)-(3,9) = "]" ├── block: ∅ ├── operator_loc: (3,10)-(3,13) = "||=" └── value: @ IntegerNode (location: (3,14)-(3,15)) - └── flags: decimal + ├── flags: decimal + └── value: 2 diff --git a/test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt b/test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt index b3a6af3ec8209a..48f377cc66769b 100644 --- a/test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt +++ b/test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt @@ -23,7 +23,8 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ IntegerNode (location: (1,35)-(1,36)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── @ SourceEncodingNode (location: (1,38)-(1,50)) diff --git a/test/prism/snapshots/whitequark/pattern_matching_blank_else.txt b/test/prism/snapshots/whitequark/pattern_matching_blank_else.txt index 308abd2f02fbe7..6015c000a98714 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_blank_else.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_blank_else.txt @@ -6,17 +6,20 @@ └── @ CaseMatchNode (location: (1,0)-(1,26)) ├── predicate: │ @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── conditions: (length: 1) │ └── @ InNode (location: (1,8)-(1,15)) │ ├── pattern: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── statements: │ │ @ StatementsNode (location: (1,14)-(1,15)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,14)-(1,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── in_loc: (1,8)-(1,10) = "in" │ └── then_loc: ∅ ├── consequent: diff --git a/test/prism/snapshots/whitequark/pattern_matching_else.txt b/test/prism/snapshots/whitequark/pattern_matching_else.txt index 944cc7b4292e4a..7f83aafe993ee8 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_else.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_else.txt @@ -6,17 +6,20 @@ └── @ CaseMatchNode (location: (1,0)-(1,29)) ├── predicate: │ @ IntegerNode (location: (1,5)-(1,6)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── conditions: (length: 1) │ └── @ InNode (location: (1,8)-(1,15)) │ ├── pattern: │ │ @ IntegerNode (location: (1,11)-(1,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ ├── statements: │ │ @ StatementsNode (location: (1,14)-(1,15)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,14)-(1,15)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 3 │ ├── in_loc: (1,8)-(1,10) = "in" │ └── then_loc: ∅ ├── consequent: @@ -26,7 +29,8 @@ │ │ @ StatementsNode (location: (1,23)-(1,24)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,23)-(1,24)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 4 │ └── end_keyword_loc: (1,26)-(1,29) = "end" ├── case_keyword_loc: (1,0)-(1,4) = "case" └── end_keyword_loc: (1,26)-(1,29) = "end" diff --git a/test/prism/snapshots/whitequark/pattern_matching_single_line.txt b/test/prism/snapshots/whitequark/pattern_matching_single_line.txt index 4cda50acb1c553..2396172dce7d77 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_single_line.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_single_line.txt @@ -6,7 +6,8 @@ ├── @ MatchRequiredNode (location: (1,0)-(1,8)) │ ├── value: │ │ @ IntegerNode (location: (1,0)-(1,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (1,5)-(1,8)) │ │ ├── constant: ∅ @@ -25,7 +26,8 @@ ├── @ MatchPredicateNode (location: (3,0)-(3,8)) │ ├── value: │ │ @ IntegerNode (location: (3,0)-(3,1)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── pattern: │ │ @ ArrayPatternNode (location: (3,5)-(3,8)) │ │ ├── constant: ∅ diff --git a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt index 4cfb5718ec3dc3..757a7780c25fcf 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt @@ -9,9 +9,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (1,1)-(1,2)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (1,4)-(1,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (1,0)-(1,1) = "[" │ │ └── closing_loc: (1,5)-(1,6) = "]" │ ├── pattern: @@ -38,9 +40,11 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ IntegerNode (location: (3,1)-(3,2)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ IntegerNode (location: (3,4)-(3,5)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── opening_loc: (3,0)-(3,1) = "[" │ │ └── closing_loc: (3,5)-(3,6) = "]" │ ├── pattern: @@ -76,7 +80,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (5,4)-(5,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (5,5)-(5,6) = "}" │ ├── pattern: @@ -120,7 +125,8 @@ │ │ │ │ └── unescaped: "a" │ │ │ ├── value: │ │ │ │ @ IntegerNode (location: (7,4)-(7,5)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── operator_loc: ∅ │ │ └── closing_loc: (7,5)-(7,6) = "}" │ ├── pattern: diff --git a/test/prism/snapshots/whitequark/postexe.txt b/test/prism/snapshots/whitequark/postexe.txt index 1c833ffaa48a88..6f273270639413 100644 --- a/test/prism/snapshots/whitequark/postexe.txt +++ b/test/prism/snapshots/whitequark/postexe.txt @@ -8,7 +8,8 @@ │ @ StatementsNode (location: (1,6)-(1,7)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── keyword_loc: (1,0)-(1,3) = "END" ├── opening_loc: (1,4)-(1,5) = "{" └── closing_loc: (1,8)-(1,9) = "}" diff --git a/test/prism/snapshots/whitequark/preexe.txt b/test/prism/snapshots/whitequark/preexe.txt index 955ba6d44426e1..5e4b88d09664af 100644 --- a/test/prism/snapshots/whitequark/preexe.txt +++ b/test/prism/snapshots/whitequark/preexe.txt @@ -8,7 +8,8 @@ │ @ StatementsNode (location: (1,8)-(1,9)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── keyword_loc: (1,0)-(1,5) = "BEGIN" ├── opening_loc: (1,6)-(1,7) = "{" └── closing_loc: (1,10)-(1,11) = "}" diff --git a/test/prism/snapshots/whitequark/range_exclusive.txt b/test/prism/snapshots/whitequark/range_exclusive.txt index 4964755075216a..f74077ce677b5f 100644 --- a/test/prism/snapshots/whitequark/range_exclusive.txt +++ b/test/prism/snapshots/whitequark/range_exclusive.txt @@ -7,8 +7,10 @@ ├── flags: exclude_end ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── right: │ @ IntegerNode (location: (1,4)-(1,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,1)-(1,4) = "..." diff --git a/test/prism/snapshots/whitequark/range_inclusive.txt b/test/prism/snapshots/whitequark/range_inclusive.txt index 04de2d8dec3b9b..18363120338b7f 100644 --- a/test/prism/snapshots/whitequark/range_inclusive.txt +++ b/test/prism/snapshots/whitequark/range_inclusive.txt @@ -7,8 +7,10 @@ ├── flags: ∅ ├── left: │ @ IntegerNode (location: (1,0)-(1,1)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── right: │ @ IntegerNode (location: (1,3)-(1,4)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 └── operator_loc: (1,1)-(1,3) = ".." diff --git a/test/prism/snapshots/whitequark/rational.txt b/test/prism/snapshots/whitequark/rational.txt index 260a5d2efc5f02..8b2cc17efdb24f 100644 --- a/test/prism/snapshots/whitequark/rational.txt +++ b/test/prism/snapshots/whitequark/rational.txt @@ -9,4 +9,5 @@ └── @ RationalNode (location: (3,0)-(3,3)) └── numeric: @ IntegerNode (location: (3,0)-(3,2)) - └── flags: decimal + ├── flags: decimal + └── value: 42 diff --git a/test/prism/snapshots/whitequark/rescue_mod_masgn.txt b/test/prism/snapshots/whitequark/rescue_mod_masgn.txt index 7fe30d4708c80d..dbe289702fc2dc 100644 --- a/test/prism/snapshots/whitequark/rescue_mod_masgn.txt +++ b/test/prism/snapshots/whitequark/rescue_mod_masgn.txt @@ -35,8 +35,10 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ IntegerNode (location: (1,24)-(1,25)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,27)-(1,28)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── opening_loc: (1,23)-(1,24) = "[" └── closing_loc: (1,28)-(1,29) = "]" diff --git a/test/prism/snapshots/whitequark/ruby_bug_10279.txt b/test/prism/snapshots/whitequark/ruby_bug_10279.txt index d1eaa26a11a966..66684350a42d9a 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_10279.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_10279.txt @@ -24,7 +24,8 @@ │ │ │ @ StatementsNode (location: (1,17)-(1,19)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,17)-(1,19)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ ├── consequent: ∅ │ │ └── end_keyword_loc: (1,20)-(1,23) = "end" │ └── operator_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_10653.txt b/test/prism/snapshots/whitequark/ruby_bug_10653.txt index 2e259785442c44..400a8c2861a60e 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_10653.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_10653.txt @@ -111,7 +111,8 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ IntegerNode (location: (5,7)-(5,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── call_operator_loc: (5,8)-(5,9) = "." │ ├── name: :tap │ ├── message_loc: (5,9)-(5,12) = "tap" @@ -166,6 +167,7 @@ │ │ @ StatementsNode (location: (5,30)-(5,31)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,30)-(5,31)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ └── end_keyword_loc: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_11380.txt b/test/prism/snapshots/whitequark/ruby_bug_11380.txt index 9fa00299c6e5a8..b7a7ef9a983282 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11380.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11380.txt @@ -42,7 +42,8 @@ │ │ └── unescaped: "a" │ ├── value: │ │ @ IntegerNode (location: (1,20)-(1,21)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: ∅ ├── closing_loc: ∅ └── block: diff --git a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt index a9e36c76a58524..320958c9d43a96 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt @@ -51,7 +51,8 @@ │ │ │ ├── closing_loc: (1,7)-(1,8) = ")" │ │ │ └── block: ∅ │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (1,12)-(1,18)) @@ -341,7 +342,8 @@ │ │ │ ├── closing_loc: (11,8)-(11,9) = ")" │ │ │ └── block: ∅ │ │ └── @ IntegerNode (location: (11,11)-(11,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (11,13)-(11,19)) @@ -636,7 +638,8 @@ │ │ │ ├── opening_loc: (21,3)-(21,4) = "{" │ │ │ └── closing_loc: (21,7)-(21,8) = "}" │ │ └── @ IntegerNode (location: (21,10)-(21,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (21,12)-(21,18)) @@ -951,7 +954,8 @@ │ │ │ ├── opening_loc: (31,3)-(31,4) = "{" │ │ │ └── closing_loc: (31,8)-(31,9) = "}" │ │ └── @ IntegerNode (location: (31,11)-(31,12)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (31,13)-(31,19)) diff --git a/test/prism/snapshots/whitequark/ruby_bug_12073.txt b/test/prism/snapshots/whitequark/ruby_bug_12073.txt index 159d272f25203e..9db30f6fec1a97 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12073.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12073.txt @@ -9,7 +9,8 @@ │ ├── name_loc: (1,0)-(1,1) = "a" │ ├── value: │ │ @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,2)-(1,3) = "=" ├── @ CallNode (location: (1,7)-(1,13)) │ ├── flags: ignore_visibility @@ -35,7 +36,8 @@ │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_12402.txt b/test/prism/snapshots/whitequark/ruby_bug_12402.txt index 34c67cb987ba7f..df5aea00c35452 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12402.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12402.txt @@ -482,7 +482,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (25,4)-(25,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 0 │ ├── closing_loc: (25,5)-(25,6) = "]" │ ├── block: ∅ │ ├── operator: :+ @@ -529,7 +530,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (27,4)-(27,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 0 ├── closing_loc: (27,5)-(27,6) = "]" ├── block: ∅ ├── operator: :+ diff --git a/test/prism/snapshots/whitequark/ruby_bug_9669.txt b/test/prism/snapshots/whitequark/ruby_bug_9669.txt index 66052061806f38..a73000bed0f950 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_9669.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_9669.txt @@ -51,7 +51,8 @@ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ IntegerNode (location: (7,0)-(7,1)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── operator_loc: ∅ │ └── closing_loc: (8,0)-(8,1) = "}" └── operator_loc: (5,2)-(5,3) = "=" diff --git a/test/prism/snapshots/whitequark/send_attr_asgn.txt b/test/prism/snapshots/whitequark/send_attr_asgn.txt index 3b38f59295c3c9..392ae5587eb50b 100644 --- a/test/prism/snapshots/whitequark/send_attr_asgn.txt +++ b/test/prism/snapshots/whitequark/send_attr_asgn.txt @@ -25,7 +25,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,8)-(1,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,9)) @@ -50,7 +51,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (3,8)-(3,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ ConstantPathWriteNode (location: (5,0)-(5,10)) @@ -74,7 +76,8 @@ │ ├── operator_loc: (5,7)-(5,8) = "=" │ └── value: │ @ IntegerNode (location: (5,9)-(5,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 └── @ CallNode (location: (7,0)-(7,10)) ├── flags: attribute_write ├── receiver: @@ -97,6 +100,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (7,9)-(7,10)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt b/test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt index 191fc53785777d..3cec95ae7cd696 100644 --- a/test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt +++ b/test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt @@ -25,6 +25,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_binary_op.txt b/test/prism/snapshots/whitequark/send_binary_op.txt index 1c91a0fdd04b26..540a7681dca624 100644 --- a/test/prism/snapshots/whitequark/send_binary_op.txt +++ b/test/prism/snapshots/whitequark/send_binary_op.txt @@ -25,7 +25,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,8)) @@ -50,7 +51,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (3,7)-(3,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (5,0)-(5,7)) @@ -75,7 +77,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (7,0)-(7,7)) @@ -100,7 +103,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (7,6)-(7,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (9,0)-(9,7)) @@ -125,7 +129,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (9,6)-(9,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (11,0)-(11,8)) @@ -150,7 +155,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (11,7)-(11,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (13,0)-(13,7)) @@ -175,7 +181,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,6)-(13,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (15,0)-(15,7)) @@ -200,7 +207,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (15,6)-(15,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (17,0)-(17,7)) @@ -225,7 +233,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (17,6)-(17,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (19,0)-(19,7)) @@ -250,7 +259,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (19,6)-(19,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (21,0)-(21,8)) @@ -275,7 +285,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (21,7)-(21,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (23,0)-(23,8)) @@ -300,7 +311,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (23,7)-(23,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (25,0)-(25,9)) @@ -325,7 +337,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (25,8)-(25,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (27,0)-(27,8)) @@ -350,7 +363,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (27,7)-(27,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (29,0)-(29,9)) @@ -375,7 +389,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (29,8)-(29,9)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (31,0)-(31,8)) @@ -400,7 +415,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (31,7)-(31,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (33,0)-(33,7)) @@ -425,7 +441,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (33,6)-(33,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (35,0)-(35,8)) @@ -450,7 +467,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (35,7)-(35,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (37,0)-(37,8)) @@ -475,7 +493,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (37,7)-(37,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (39,0)-(39,7)) @@ -500,7 +519,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (39,6)-(39,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: ∅ └── @ CallNode (location: (41,0)-(41,7)) @@ -525,6 +545,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (41,6)-(41,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: ∅ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_block_chain_cmd.txt b/test/prism/snapshots/whitequark/send_block_chain_cmd.txt index a6d69767d1a5e4..4013888882b747 100644 --- a/test/prism/snapshots/whitequark/send_block_chain_cmd.txt +++ b/test/prism/snapshots/whitequark/send_block_chain_cmd.txt @@ -18,7 +18,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (1,7)-(1,13)) @@ -62,7 +63,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,5)-(3,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (3,7)-(3,13)) @@ -112,7 +114,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (5,5)-(5,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (5,7)-(5,13)) @@ -149,7 +152,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (7,5)-(7,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (7,7)-(7,13)) @@ -193,7 +197,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (9,5)-(9,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (9,7)-(9,13)) @@ -243,7 +248,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (11,5)-(11,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── closing_loc: ∅ │ │ └── block: │ │ @ BlockNode (location: (11,7)-(11,13)) @@ -287,7 +293,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (13,5)-(13,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (13,7)-(13,13)) diff --git a/test/prism/snapshots/whitequark/send_call.txt b/test/prism/snapshots/whitequark/send_call.txt index bfd554e4953553..48063e01212fd2 100644 --- a/test/prism/snapshots/whitequark/send_call.txt +++ b/test/prism/snapshots/whitequark/send_call.txt @@ -25,7 +25,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── closing_loc: (1,6)-(1,7) = ")" │ └── block: ∅ └── @ CallNode (location: (3,0)-(3,8)) @@ -50,6 +51,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (3,6)-(3,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (3,7)-(3,8) = ")" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_index.txt b/test/prism/snapshots/whitequark/send_index.txt index 5e00593222a0a3..6c9e08f2eace31 100644 --- a/test/prism/snapshots/whitequark/send_index.txt +++ b/test/prism/snapshots/whitequark/send_index.txt @@ -25,8 +25,10 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_index_asgn.txt b/test/prism/snapshots/whitequark/send_index_asgn.txt index f34d35147225bc..9d2e6efcb67d0b 100644 --- a/test/prism/snapshots/whitequark/send_index_asgn.txt +++ b/test/prism/snapshots/whitequark/send_index_asgn.txt @@ -25,10 +25,13 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_index_asgn_legacy.txt b/test/prism/snapshots/whitequark/send_index_asgn_legacy.txt index f34d35147225bc..9d2e6efcb67d0b 100644 --- a/test/prism/snapshots/whitequark/send_index_asgn_legacy.txt +++ b/test/prism/snapshots/whitequark/send_index_asgn_legacy.txt @@ -25,10 +25,13 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (1,7)-(1,8)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (1,12)-(1,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_index_legacy.txt b/test/prism/snapshots/whitequark/send_index_legacy.txt index 5e00593222a0a3..6c9e08f2eace31 100644 --- a/test/prism/snapshots/whitequark/send_index_legacy.txt +++ b/test/prism/snapshots/whitequark/send_index_legacy.txt @@ -25,8 +25,10 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ IntegerNode (location: (1,4)-(1,5)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── @ IntegerNode (location: (1,7)-(1,8)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 2 ├── closing_loc: (1,8)-(1,9) = "]" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt b/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt index eff1cab3173b93..747656af6bca90 100644 --- a/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt +++ b/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt @@ -23,7 +23,8 @@ │ │ │ │ ├── name_loc: (1,3)-(1,5) = "a:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (1,6)-(1,7)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: ∅ │ │ ├── locals: (length: 0) diff --git a/test/prism/snapshots/whitequark/send_op_asgn_conditional.txt b/test/prism/snapshots/whitequark/send_op_asgn_conditional.txt index 102a5af5b54e63..05966fc5a30de8 100644 --- a/test/prism/snapshots/whitequark/send_op_asgn_conditional.txt +++ b/test/prism/snapshots/whitequark/send_op_asgn_conditional.txt @@ -23,4 +23,5 @@ ├── operator_loc: (1,5)-(1,8) = "&&=" └── value: @ IntegerNode (location: (1,9)-(1,10)) - └── flags: decimal + ├── flags: decimal + └── value: 1 diff --git a/test/prism/snapshots/whitequark/send_self.txt b/test/prism/snapshots/whitequark/send_self.txt index fe1e8d11578f83..41fd822110c6a4 100644 --- a/test/prism/snapshots/whitequark/send_self.txt +++ b/test/prism/snapshots/whitequark/send_self.txt @@ -35,6 +35,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (5,4)-(5,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (5,5)-(5,6) = ")" └── block: ∅ diff --git a/test/prism/snapshots/whitequark/send_self_block.txt b/test/prism/snapshots/whitequark/send_self_block.txt index d94463d8b0d046..c92935603b70d2 100644 --- a/test/prism/snapshots/whitequark/send_self_block.txt +++ b/test/prism/snapshots/whitequark/send_self_block.txt @@ -63,7 +63,8 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ IntegerNode (location: (7,4)-(7,5)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── closing_loc: (7,5)-(7,6) = ")" └── block: @ BlockNode (location: (7,7)-(7,10)) diff --git a/test/prism/snapshots/whitequark/space_args_arg.txt b/test/prism/snapshots/whitequark/space_args_arg.txt index a87138db626dfc..55750d2b615342 100644 --- a/test/prism/snapshots/whitequark/space_args_arg.txt +++ b/test/prism/snapshots/whitequark/space_args_arg.txt @@ -19,7 +19,8 @@ │ │ @ StatementsNode (location: (1,5)-(1,6)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (1,4)-(1,5) = "(" │ └── closing_loc: (1,6)-(1,7) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/space_args_arg_block.txt b/test/prism/snapshots/whitequark/space_args_arg_block.txt index de4a6022c02dc4..a6224bcca109a0 100644 --- a/test/prism/snapshots/whitequark/space_args_arg_block.txt +++ b/test/prism/snapshots/whitequark/space_args_arg_block.txt @@ -29,7 +29,8 @@ │ │ │ @ StatementsNode (location: (1,9)-(1,10)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,9)-(1,10)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (1,8)-(1,9) = "(" │ │ └── closing_loc: (1,10)-(1,11) = ")" │ ├── closing_loc: ∅ @@ -66,7 +67,8 @@ │ │ │ @ StatementsNode (location: (3,10)-(3,11)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (3,10)-(3,11)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (3,9)-(3,10) = "(" │ │ └── closing_loc: (3,11)-(3,12) = ")" │ ├── closing_loc: ∅ @@ -93,7 +95,8 @@ │ │ @ StatementsNode (location: (5,5)-(5,6)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (5,5)-(5,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (5,4)-(5,5) = "(" │ └── closing_loc: (5,6)-(5,7) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/space_args_arg_call.txt b/test/prism/snapshots/whitequark/space_args_arg_call.txt index b47b14afab674e..767b099a8bbf66 100644 --- a/test/prism/snapshots/whitequark/space_args_arg_call.txt +++ b/test/prism/snapshots/whitequark/space_args_arg_call.txt @@ -22,7 +22,8 @@ │ │ │ @ StatementsNode (location: (1,5)-(1,6)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ ├── opening_loc: (1,4)-(1,5) = "(" │ │ └── closing_loc: (1,6)-(1,7) = ")" │ ├── call_operator_loc: (1,7)-(1,8) = "." diff --git a/test/prism/snapshots/whitequark/space_args_arg_newline.txt b/test/prism/snapshots/whitequark/space_args_arg_newline.txt index eab02432749ce8..7727a5ddd9a99c 100644 --- a/test/prism/snapshots/whitequark/space_args_arg_newline.txt +++ b/test/prism/snapshots/whitequark/space_args_arg_newline.txt @@ -19,7 +19,8 @@ │ │ @ StatementsNode (location: (1,5)-(1,6)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,5)-(1,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── opening_loc: (1,4)-(1,5) = "(" │ └── closing_loc: (2,0)-(2,1) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ternary.txt b/test/prism/snapshots/whitequark/ternary.txt index 09312e3179c303..fa637ffb4e01bc 100644 --- a/test/prism/snapshots/whitequark/ternary.txt +++ b/test/prism/snapshots/whitequark/ternary.txt @@ -21,7 +21,8 @@ │ @ StatementsNode (location: (1,6)-(1,7)) │ └── body: (length: 1) │ └── @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── consequent: │ @ ElseNode (location: (1,8)-(1,11)) │ ├── else_keyword_loc: (1,8)-(1,9) = ":" @@ -29,6 +30,7 @@ │ │ @ StatementsNode (location: (1,10)-(1,11)) │ │ └── body: (length: 1) │ │ └── @ IntegerNode (location: (1,10)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── end_keyword_loc: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt b/test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt index b66406af52618b..833afcff42bac0 100644 --- a/test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt +++ b/test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt @@ -9,7 +9,8 @@ │ ├── name_loc: (1,0)-(1,1) = "t" │ ├── value: │ │ @ IntegerNode (location: (1,2)-(1,3)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator_loc: (1,1)-(1,2) = "=" └── @ IfNode (location: (1,4)-(1,13)) ├── if_keyword_loc: ∅ diff --git a/test/prism/snapshots/whitequark/trailing_forward_arg.txt b/test/prism/snapshots/whitequark/trailing_forward_arg.txt index b58eb511498270..e12dad132bbed6 100644 --- a/test/prism/snapshots/whitequark/trailing_forward_arg.txt +++ b/test/prism/snapshots/whitequark/trailing_forward_arg.txt @@ -41,7 +41,8 @@ │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── @ IntegerNode (location: (1,27)-(1,29)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 42 │ │ └── @ ForwardingArgumentsNode (location: (1,31)-(1,34)) │ ├── closing_loc: (1,34)-(1,35) = ")" │ └── block: ∅ diff --git a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt index 4bc54ba22c0c3a..75be379e2e4a5e 100644 --- a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt +++ b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt @@ -16,7 +16,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (1,8)-(1,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ ├── closing_loc: ∅ │ └── block: ∅ ├── @ CallNode (location: (3,0)-(3,8)) @@ -26,7 +27,8 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ IntegerNode (location: (3,1)-(3,2)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 2 │ │ ├── call_operator_loc: ∅ │ │ ├── name: :** │ │ ├── message_loc: (3,3)-(3,5) = "**" @@ -36,7 +38,8 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ IntegerNode (location: (3,6)-(3,8)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 10 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ @@ -62,7 +65,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,8)-(5,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ ├── closing_loc: ∅ │ └── block: ∅ ├── call_operator_loc: ∅ diff --git a/test/prism/snapshots/whitequark/undef.txt b/test/prism/snapshots/whitequark/undef.txt index 9889a5a5257f65..5e6b5c7b7695c3 100644 --- a/test/prism/snapshots/whitequark/undef.txt +++ b/test/prism/snapshots/whitequark/undef.txt @@ -32,7 +32,8 @@ │ │ │ @ StatementsNode (location: (1,24)-(1,25)) │ │ │ └── body: (length: 1) │ │ │ └── @ IntegerNode (location: (1,24)-(1,25)) - │ │ │ └── flags: decimal + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 │ │ └── closing_loc: (1,25)-(1,26) = "}" │ └── closing_loc: (1,26)-(1,27) = "\"" └── keyword_loc: (1,0)-(1,5) = "undef" diff --git a/test/prism/snapshots/whitequark/var_and_asgn.txt b/test/prism/snapshots/whitequark/var_and_asgn.txt index fc746a93506104..a3c90f804cf074 100644 --- a/test/prism/snapshots/whitequark/var_and_asgn.txt +++ b/test/prism/snapshots/whitequark/var_and_asgn.txt @@ -8,6 +8,7 @@ ├── operator_loc: (1,2)-(1,5) = "&&=" ├── value: │ @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── name: :a └── depth: 0 diff --git a/test/prism/snapshots/whitequark/var_op_asgn.txt b/test/prism/snapshots/whitequark/var_op_asgn.txt index 7160141b07549a..f423a62dee9c8b 100644 --- a/test/prism/snapshots/whitequark/var_op_asgn.txt +++ b/test/prism/snapshots/whitequark/var_op_asgn.txt @@ -9,7 +9,8 @@ │ ├── operator_loc: (1,6)-(1,8) = "|=" │ ├── value: │ │ @ IntegerNode (location: (1,9)-(1,11)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator: :| ├── @ InstanceVariableOperatorWriteNode (location: (3,0)-(3,7)) │ ├── name: :@a @@ -17,14 +18,16 @@ │ ├── operator_loc: (3,3)-(3,5) = "|=" │ ├── value: │ │ @ IntegerNode (location: (3,6)-(3,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── operator: :| ├── @ LocalVariableOperatorWriteNode (location: (5,0)-(5,6)) │ ├── name_loc: (5,0)-(5,1) = "a" │ ├── operator_loc: (5,2)-(5,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (5,5)-(5,6)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── name: :a │ ├── operator: :+ │ └── depth: 0 @@ -42,7 +45,8 @@ │ ├── operator_loc: (7,13)-(7,15) = "|=" │ ├── value: │ │ @ IntegerNode (location: (7,16)-(7,18)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 10 │ └── operator: :| ├── locals: [] ├── def_keyword_loc: (7,0)-(7,3) = "def" diff --git a/test/prism/snapshots/whitequark/var_or_asgn.txt b/test/prism/snapshots/whitequark/var_or_asgn.txt index d5064bc55b5d50..a0531d2c306a9e 100644 --- a/test/prism/snapshots/whitequark/var_or_asgn.txt +++ b/test/prism/snapshots/whitequark/var_or_asgn.txt @@ -8,6 +8,7 @@ ├── operator_loc: (1,2)-(1,5) = "||=" ├── value: │ @ IntegerNode (location: (1,6)-(1,7)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 1 ├── name: :a └── depth: 0 diff --git a/test/prism/snapshots/whitequark/when_splat.txt b/test/prism/snapshots/whitequark/when_splat.txt index c9b922da315877..ea991e70411f48 100644 --- a/test/prism/snapshots/whitequark/when_splat.txt +++ b/test/prism/snapshots/whitequark/when_splat.txt @@ -20,7 +20,8 @@ │ │ ├── keyword_loc: (1,10)-(1,14) = "when" │ │ ├── conditions: (length: 2) │ │ │ ├── @ IntegerNode (location: (1,15)-(1,16)) - │ │ │ │ └── flags: decimal + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 1 │ │ │ └── @ SplatNode (location: (1,18)-(1,22)) │ │ │ ├── operator_loc: (1,18)-(1,19) = "*" │ │ │ └── expression: diff --git a/test/prism/snapshots/yield.txt b/test/prism/snapshots/yield.txt index 9c1fd59d34b8bd..896dbac13f05ea 100644 --- a/test/prism/snapshots/yield.txt +++ b/test/prism/snapshots/yield.txt @@ -21,7 +21,8 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ IntegerNode (location: (5,6)-(5,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ └── rparen_loc: (5,7)-(5,8) = ")" └── @ YieldNode (location: (7,0)-(7,14)) ├── keyword_loc: (7,0)-(7,5) = "yield" @@ -31,9 +32,12 @@ │ ├── flags: ∅ │ └── arguments: (length: 3) │ ├── @ IntegerNode (location: (7,6)-(7,7)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 1 │ ├── @ IntegerNode (location: (7,9)-(7,10)) - │ │ └── flags: decimal + │ │ ├── flags: decimal + │ │ └── value: 2 │ └── @ IntegerNode (location: (7,12)-(7,13)) - │ └── flags: decimal + │ ├── flags: decimal + │ └── value: 3 └── rparen_loc: (7,13)-(7,14) = ")" From 5e0589cf52113e012b48044e7e8773a2ab3ee58d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 22 Feb 2024 15:53:28 -0500 Subject: [PATCH 012/147] [ruby/prism] Parse float values https://github.com/ruby/prism/commit/9137226a52 --- lib/prism/node_ext.rb | 7 -- prism/config.yml | 4 + prism/diagnostic.c | 2 + prism/diagnostic.h | 2 + prism/prism.c | 92 +++++++++++++++++-- prism/prism.h | 1 + prism/templates/ext/prism/api_node.c.erb | 3 + prism/templates/include/prism/ast.h.erb | 1 + prism/templates/lib/prism/dot_visitor.rb.erb | 2 +- prism/templates/lib/prism/node.rb.erb | 2 +- prism/templates/lib/prism/serialize.rb.erb | 6 ++ prism/templates/src/node.c.erb | 8 +- prism/templates/src/prettyprint.c.erb | 2 + prism/templates/src/serialize.c.erb | 2 + prism/templates/template.rb | 17 ++++ prism/util/pm_buffer.c | 9 ++ prism/util/pm_buffer.h | 8 ++ test/prism/snapshots/numbers.txt | 5 + test/prism/snapshots/patterns.txt | 6 ++ .../seattlerb/float_with_if_modifier.txt | 1 + .../snapshots/seattlerb/uminus_float.txt | 1 + test/prism/snapshots/symbols.txt | 1 + .../unparser/corpus/literal/literal.txt | 12 +++ .../unparser/corpus/semantic/literal.txt | 6 ++ test/prism/snapshots/whitequark/complex.txt | 2 + test/prism/snapshots/whitequark/float.txt | 2 + .../lparenarg_after_lvar__since_25.txt | 2 + test/prism/snapshots/whitequark/rational.txt | 1 + .../snapshots/whitequark/ruby_bug_11873_a.txt | 12 +++ .../whitequark/unary_num_pow_precedence.txt | 2 + 30 files changed, 199 insertions(+), 22 deletions(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index a9a0115a09d890..c0f485f675de00 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -57,13 +57,6 @@ class XStringNode < Node private_constant :HeredocQuery - class FloatNode < Node - # Returns the value of the node as a Ruby Float. - def value - Float(slice) - end - end - class ImaginaryNode < Node # Returns the value of the node as a Ruby Complex. def value diff --git a/prism/config.yml b/prism/config.yml index 33abcc623c0f11..af4bc42fb6104c 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1396,6 +1396,10 @@ nodes: baz if foo .. bar ^^^^^^^^^^ - name: FloatNode + fields: + - name: value + type: double + comment: The value of the floating point number as a Float. comment: | Represents a floating point number literal. diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 601f9671167170..2040387d807be0 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -179,6 +179,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_FATAL }, [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_FATAL }, [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_FATAL }, [PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_FATAL }, [PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_FATAL }, [PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_LEVEL_FATAL }, @@ -307,6 +308,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT }, + [PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE } }; static inline const char * diff --git a/prism/diagnostic.h b/prism/diagnostic.h index eb60eea8fcb7de..7419c0e791ae52 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -176,6 +176,7 @@ typedef enum { PM_ERR_EXPECT_STRING_CONTENT, PM_ERR_EXPECT_WHEN_DELIMITER, PM_ERR_EXPRESSION_BARE_HASH, + PM_ERR_FLOAT_PARSE, PM_ERR_FOR_COLLECTION, PM_ERR_FOR_IN, PM_ERR_FOR_INDEX, @@ -305,6 +306,7 @@ typedef enum { PM_WARN_AMBIGUOUS_SLASH, PM_WARN_EQUAL_IN_CONDITIONAL, PM_WARN_END_IN_METHOD, + PM_WARN_FLOAT_OUT_OF_RANGE, // This is the number of diagnostic codes. PM_DIAGNOSTIC_ID_LEN, diff --git a/prism/prism.c b/prism/prism.c index e14911167ab1f9..4f268fc952be3f 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3138,6 +3138,70 @@ pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) { return node; } +/** + * Parse the value of a double, add appropriate errors if there is an issue, and + * return the value that should be saved on the PM_FLOAT_NODE node. + */ +static double +pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { + ptrdiff_t diff = token->end - token->start; + if (diff <= 0) return 0.0; + + // First, get a buffer of the content. + size_t length = (size_t) diff; + char *buffer = malloc(sizeof(char) * (length + 1)); + memcpy((void *) buffer, token->start, length); + + // Next, handle underscores by removing them from the buffer. + for (size_t index = 0; index < length; index++) { + if (buffer[index] == '_') { + memmove((void *) (buffer + index), (void *) (buffer + index + 1), length - index); + length--; + } + } + + // Null-terminate the buffer so that strtod cannot read off the end. + buffer[length] = '\0'; + + // Now, call strtod to parse the value. Note that CRuby has their own + // version of strtod which avoids locales. We're okay using the locale-aware + // version because we've already validated through the parser that the token + // is in a valid format. + errno = 0; + char *eptr; + double value = strtod(buffer, &eptr); + + // This should never happen, because we've already checked that the token + // is in a valid format. However it's good to be safe. + if ((eptr != buffer + length) || (errno != 0 && errno != ERANGE)) { + PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, (*token), PM_ERR_FLOAT_PARSE); + free((void *) buffer); + return 0.0; + } + + // If errno is set, then it should only be ERANGE. At this point we need to + // check if it's infinity (it should be). + if (errno == ERANGE) { + int warn_width; + const char *ellipsis; + + if (length > 20) { + warn_width = 20; + ellipsis = "..."; + } else { + warn_width = (int) length; + ellipsis = ""; + } + + pm_diagnostic_list_append_format(&parser->warning_list, token->start, token->end, PM_WARN_FLOAT_OUT_OF_RANGE, warn_width, (const char *) token->start, ellipsis); + value = (value < 0x0) ? -HUGE_VAL : HUGE_VAL; + } + + // Finally we can free the buffer and return the value. + free((void *) buffer); + return value; +} + /** * Allocate and initialize a new FloatNode node. */ @@ -3146,11 +3210,14 @@ pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) { assert(token->type == PM_TOKEN_FLOAT); pm_float_node_t *node = PM_ALLOC_NODE(parser, pm_float_node_t); - *node = (pm_float_node_t) {{ - .type = PM_FLOAT_NODE, - .flags = PM_NODE_FLAG_STATIC_LITERAL, - .location = PM_LOCATION_TOKEN_VALUE(token) - }}; + *node = (pm_float_node_t) { + { + .type = PM_FLOAT_NODE, + .flags = PM_NODE_FLAG_STATIC_LITERAL, + .location = PM_LOCATION_TOKEN_VALUE(token) + }, + .value = pm_double_parse(parser, token) + }; return node; } @@ -14293,13 +14360,18 @@ parse_pattern(pm_parser_t *parser, bool top_pattern, pm_diagnostic_id_t diag_id) static inline void parse_negative_numeric(pm_node_t *node) { switch (PM_NODE_TYPE(node)) { - case PM_INTEGER_NODE: - node->location.start--; - ((pm_integer_node_t *) node)->value.negative = true; + case PM_INTEGER_NODE: { + pm_integer_node_t *cast = (pm_integer_node_t *) node; + cast->base.location.start--; + cast->value.negative = true; break; - case PM_FLOAT_NODE: - node->location.start--; + } + case PM_FLOAT_NODE: { + pm_float_node_t *cast = (pm_float_node_t *) node; + cast->base.location.start--; + cast->value = -cast->value; break; + } case PM_RATIONAL_NODE: node->location.start--; parse_negative_numeric(((pm_rational_node_t *) node)->numeric); diff --git a/prism/prism.h b/prism/prism.h index f26ca0c7848281..e24dbf5cad06e8 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb index c669a4aac9e7fb..1e7663ac8533f4 100644 --- a/prism/templates/ext/prism/api_node.c.erb +++ b/prism/templates/ext/prism/api_node.c.erb @@ -213,6 +213,9 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi <%- when Prism::IntegerField -%> #line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>); + <%- when Prism::DoubleField -%> +#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" + argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb index d1c94fe541fa51..ac528a086bb61c 100644 --- a/prism/templates/include/prism/ast.h.erb +++ b/prism/templates/include/prism/ast.h.erb @@ -185,6 +185,7 @@ typedef struct pm_<%= node.human %> { when Prism::UInt8Field then "uint8_t #{field.name}" when Prism::UInt32Field then "uint32_t #{field.name}" when Prism::IntegerField then "pm_integer_t #{field.name}" + when Prism::DoubleField then "double #{field.name}" else raise field.class.name end %>; diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb index 7689bc913f5cf9..1dc48d265ddd92 100644 --- a/prism/templates/lib/prism/dot_visitor.rb.erb +++ b/prism/templates/lib/prism/dot_visitor.rb.erb @@ -133,7 +133,7 @@ module Prism else table.field("<%= field.name %>", "[]") end - <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField, Prism::IntegerField -%> + <%- when Prism::StringField, Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::ConstantListField, Prism::IntegerField, Prism::DoubleField -%> table.field("<%= field.name %>", node.<%= field.name %>.inspect) <%- when Prism::LocationField -%> table.field("<%= field.name %>", location_inspect(node.<%= field.name %>)) diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index df8f16a1e8ffd9..19fcda936fae56 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -281,7 +281,7 @@ module Prism inspector << "<%= pointer %><%= field.name %>:\n" inspector << <%= field.name %>.inspect(inspector.child_inspector("<%= preadd %>")).delete_prefix(inspector.prefix) end - <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field, Prism::IntegerField -%> + <%- when Prism::ConstantField, Prism::StringField, Prism::UInt8Field, Prism::UInt32Field, Prism::IntegerField, Prism::DoubleField -%> inspector << "<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n" <%- when Prism::OptionalConstantField -%> if (<%= field.name %> = self.<%= field.name %>).nil? diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 0214913c19b0fe..1356496a5eaec0 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -183,6 +183,10 @@ module Prism value end + def load_double + io.read(8).unpack1("D") + end + def load_serialized_length io.read(4).unpack1("L") end @@ -300,6 +304,7 @@ module Prism when Prism::UInt8Field then "io.getbyte" when Prism::UInt32Field, Prism::FlagsField then "load_varuint" when Prism::IntegerField then "load_integer" + when Prism::DoubleField then "load_double" else raise end } + ["location"]).join(", ") -%>) @@ -336,6 +341,7 @@ module Prism when Prism::UInt8Field then "io.getbyte" when Prism::UInt32Field, Prism::FlagsField then "load_varuint" when Prism::IntegerField then "load_integer" + when Prism::DoubleField then "load_double" else raise end } + ["location"]).join(", ") -%>) diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index 082d1a36980032..89c73451e8e457 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -56,12 +56,12 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { <%- nodes.each do |node| -%> #line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>" case <%= node.type %>: { - <%- if node.fields.any? { |field| ![Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField].include?(field.class) } -%> + <%- if node.fields.any? { |field| ![Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField, Prism::DoubleField].include?(field.class) } -%> pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node; <%- end -%> <%- node.fields.each do |field| -%> <%- case field -%> - <%- when Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField -%> + <%- when Prism::LocationField, Prism::OptionalLocationField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::ConstantField, Prism::OptionalConstantField, Prism::DoubleField -%> <%- when Prism::NodeField -%> pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>); <%- when Prism::OptionalNodeField -%> @@ -107,7 +107,7 @@ pm_node_memsize_node(pm_node_t *node, pm_memsize_t *memsize) { memsize->memsize += sizeof(*cast); <%- node.fields.each do |field| -%> <%- case field -%> - <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::LocationField, Prism::OptionalLocationField -%> + <%- when Prism::ConstantField, Prism::OptionalConstantField, Prism::UInt8Field, Prism::UInt32Field, Prism::FlagsField, Prism::LocationField, Prism::OptionalLocationField, Prism::DoubleField -%> <%- when Prism::NodeField -%> pm_node_memsize_node((pm_node_t *)cast-><%= field.name %>, memsize); <%- when Prism::OptionalNodeField -%> @@ -276,6 +276,8 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no pm_buffer_append_string(buffer, "]}", 2); } } + <%- when Prism::DoubleField -%> + pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>); <%- else -%> <%- raise %> <%- end -%> diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index dafe3671f12f19..67a2f444e65fa6 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -156,6 +156,8 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm } pm_buffer_append_string(output_buffer, "]\n", 2); } + <%- when Prism::DoubleField -%> + pm_buffer_append_format(output_buffer, " %f\n", cast-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb index 9e0fe1e4e877ec..49fd5882ee54c6 100644 --- a/prism/templates/src/serialize.c.erb +++ b/prism/templates/src/serialize.c.erb @@ -127,6 +127,8 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) { pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK)); <%- when Prism::IntegerField -%> pm_serialize_integer(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer); + <%- when Prism::DoubleField -%> + pm_buffer_append_double(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>); <%- else -%> <%- raise -%> <%- end -%> diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 8e20042bb82877..12749add22d24e 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -270,6 +270,22 @@ def java_type end end + # This represents a double-precision floating point number. When it gets to + # Ruby it will be a Float. + class DoubleField < Field + def rbs_class + "Float" + end + + def rbi_class + "Float" + end + + def java_type + "double" + end + end + # This class represents a node in the tree, configured by the config.yml file # in YAML format. It contains information about the name of the node and the # various child nodes it contains. @@ -332,6 +348,7 @@ def field_type_for(name) when "uint32" then UInt32Field when "flags" then FlagsField when "integer" then IntegerField + when "double" then DoubleField else raise("Unknown field type: #{name.inspect}") end end diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c index 80a65f02b58e55..048bc9736367b5 100644 --- a/prism/util/pm_buffer.c +++ b/prism/util/pm_buffer.c @@ -163,6 +163,15 @@ pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value) { pm_buffer_append_varuint(buffer, unsigned_int); } +/** + * Append a double to the buffer. + */ +void +pm_buffer_append_double(pm_buffer_t *buffer, double value) { + const void *source = &value; + pm_buffer_append(buffer, source, sizeof(double)); +} + /** * Append a slice of source code to the buffer. */ diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h index a798dd1d171aaa..d8ec8180e799bb 100644 --- a/prism/util/pm_buffer.h +++ b/prism/util/pm_buffer.h @@ -129,6 +129,14 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value); */ void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value); +/** + * Append a double to the buffer. + * + * @param buffer The buffer to append to. + * @param value The double to append. + */ +void pm_buffer_append_double(pm_buffer_t *buffer, double value); + /** * The different types of escaping that can be performed by the buffer when * appending a slice of Ruby source code. diff --git a/test/prism/snapshots/numbers.txt b/test/prism/snapshots/numbers.txt index abcbf44c5e8058..740f3f5a2a1684 100644 --- a/test/prism/snapshots/numbers.txt +++ b/test/prism/snapshots/numbers.txt @@ -10,6 +10,7 @@ │ ├── flags: decimal │ └── value: 1 ├── @ FloatNode (location: (5,0)-(5,3)) + │ └── value: 1.0 ├── @ IntegerNode (location: (7,0)-(7,1)) │ ├── flags: decimal │ └── value: 2 @@ -81,11 +82,13 @@ ├── @ RationalNode (location: (47,0)-(47,4)) │ └── numeric: │ @ FloatNode (location: (47,0)-(47,3)) + │ └── value: 1.2 ├── @ ImaginaryNode (location: (49,0)-(49,5)) │ └── numeric: │ @ RationalNode (location: (49,0)-(49,4)) │ └── numeric: │ @ FloatNode (location: (49,0)-(49,3)) + │ └── value: 1.2 ├── @ ImaginaryNode (location: (51,0)-(51,4)) │ └── numeric: │ @ RationalNode (location: (51,0)-(51,3)) @@ -96,11 +99,13 @@ ├── @ RationalNode (location: (53,0)-(53,5)) │ └── numeric: │ @ FloatNode (location: (53,0)-(53,4)) + │ └── value: -1.2 ├── @ ImaginaryNode (location: (55,0)-(55,6)) │ └── numeric: │ @ RationalNode (location: (55,0)-(55,5)) │ └── numeric: │ @ FloatNode (location: (55,0)-(55,4)) + │ └── value: -1.2 ├── @ RationalNode (location: (57,0)-(57,4)) │ └── numeric: │ @ IntegerNode (location: (57,0)-(57,3)) diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 7080749a9e2924..96205349d33063 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -51,6 +51,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FloatNode (location: (3,7)-(3,10)) + │ │ └── value: 1.0 │ └── operator_loc: (3,4)-(3,6) = "=>" ├── @ MatchRequiredNode (location: (4,0)-(4,9)) │ ├── value: @@ -544,8 +545,10 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ FloatNode (location: (29,7)-(29,10)) + │ │ │ └── value: 1.0 │ │ ├── right: │ │ │ @ FloatNode (location: (29,14)-(29,17)) + │ │ │ └── value: 1.0 │ │ └── operator_loc: (29,11)-(29,13) = ".." │ └── operator_loc: (29,4)-(29,6) = "=>" ├── @ MatchRequiredNode (location: (30,0)-(30,15)) @@ -2426,6 +2429,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ FloatNode (location: (106,7)-(106,10)) + │ │ └── value: 1.0 │ └── operator_loc: (106,4)-(106,6) = "in" ├── @ MatchPredicateNode (location: (107,0)-(107,9)) │ ├── value: @@ -2966,6 +2970,7 @@ │ │ └── @ InNode (location: (137,10)-(137,21)) │ │ ├── pattern: │ │ │ @ FloatNode (location: (137,13)-(137,16)) + │ │ │ └── value: 1.0 │ │ ├── statements: ∅ │ │ ├── in_loc: (137,10)-(137,12) = "in" │ │ └── then_loc: (137,17)-(137,21) = "then" @@ -3681,6 +3686,7 @@ │ │ │ │ @ StatementsNode (location: (164,13)-(164,16)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ FloatNode (location: (164,13)-(164,16)) + │ │ │ │ └── value: 1.0 │ │ │ ├── consequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ ├── statements: ∅ diff --git a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt index 5cf12848c4838a..9c1da70f242576 100644 --- a/test/prism/snapshots/seattlerb/float_with_if_modifier.txt +++ b/test/prism/snapshots/seattlerb/float_with_if_modifier.txt @@ -12,5 +12,6 @@ │ @ StatementsNode (location: (1,0)-(1,3)) │ └── body: (length: 1) │ └── @ FloatNode (location: (1,0)-(1,3)) + │ └── value: 1.0 ├── consequent: ∅ └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/uminus_float.txt b/test/prism/snapshots/seattlerb/uminus_float.txt index b509e2f7f365bd..0578dbbd6806a1 100644 --- a/test/prism/snapshots/seattlerb/uminus_float.txt +++ b/test/prism/snapshots/seattlerb/uminus_float.txt @@ -4,3 +4,4 @@ @ StatementsNode (location: (1,0)-(1,4)) └── body: (length: 1) └── @ FloatNode (location: (1,0)-(1,4)) + └── value: -0.0 diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt index 4fbb277c6edc2b..c34be74b37d506 100644 --- a/test/prism/snapshots/symbols.txt +++ b/test/prism/snapshots/symbols.txt @@ -144,6 +144,7 @@ │ │ │ ├── flags: decimal │ │ │ └── value: 1 │ │ ├── @ FloatNode (location: (29,4)-(29,7)) + │ │ │ └── value: 1.0 │ │ ├── @ RationalNode (location: (29,9)-(29,11)) │ │ │ └── numeric: │ │ │ @ IntegerNode (location: (29,9)-(29,10)) diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt index 6a3d817a6e401f..8ed1bf5fe9bdd7 100644 --- a/test/prism/snapshots/unparser/corpus/literal/literal.txt +++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt @@ -319,9 +319,11 @@ ├── @ RationalNode (location: (20,0)-(20,4)) │ └── numeric: │ @ FloatNode (location: (20,0)-(20,3)) + │ └── value: 1.5 ├── @ RationalNode (location: (21,0)-(21,4)) │ └── numeric: │ @ FloatNode (location: (21,0)-(21,3)) + │ └── value: 1.3 ├── @ ImaginaryNode (location: (22,0)-(22,2)) │ └── numeric: │ @ IntegerNode (location: (22,0)-(22,1)) @@ -335,9 +337,11 @@ ├── @ ImaginaryNode (location: (24,0)-(24,4)) │ └── numeric: │ @ FloatNode (location: (24,0)-(24,3)) + │ └── value: 0.6 ├── @ ImaginaryNode (location: (25,0)-(25,5)) │ └── numeric: │ @ FloatNode (location: (25,0)-(25,4)) + │ └── value: -0.6 ├── @ ImaginaryNode (location: (26,0)-(26,32)) │ └── numeric: │ @ IntegerNode (location: (26,0)-(26,31)) @@ -711,6 +715,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (60,1)-(60,4)) + │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ │ │ │ ├── message_loc: (60,5)-(60,6) = "/" @@ -720,6 +725,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (60,7)-(60,10)) + │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── opening_loc: (60,0)-(60,1) = "(" @@ -744,6 +750,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (61,4)-(61,7)) + │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ │ │ │ ├── message_loc: (61,8)-(61,9) = "/" @@ -753,6 +760,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (61,10)-(61,13)) + │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── opening_loc: (61,3)-(61,4) = "(" @@ -769,6 +777,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── receiver: │ │ │ │ @ FloatNode (location: (62,1)-(62,4)) + │ │ │ │ └── value: 0.0 │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :/ │ │ │ ├── message_loc: (62,5)-(62,6) = "/" @@ -778,6 +787,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ FloatNode (location: (62,7)-(62,10)) + │ │ │ │ └── value: 0.0 │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── opening_loc: (62,0)-(62,1) = "(" @@ -788,7 +798,9 @@ │ │ └── value: 100 │ └── operator_loc: (62,11)-(62,13) = ".." ├── @ FloatNode (location: (63,0)-(63,4)) + │ └── value: -0.1 ├── @ FloatNode (location: (64,0)-(64,3)) + │ └── value: 0.1 ├── @ ArrayNode (location: (65,0)-(65,6)) │ ├── flags: ∅ │ ├── elements: (length: 2) diff --git a/test/prism/snapshots/unparser/corpus/semantic/literal.txt b/test/prism/snapshots/unparser/corpus/semantic/literal.txt index 915254d3728d95..7f76e2f561faab 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/literal.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/literal.txt @@ -6,6 +6,7 @@ ├── @ RationalNode (location: (1,0)-(1,4)) │ └── numeric: │ @ FloatNode (location: (1,0)-(1,3)) + │ └── value: 1.0 ├── @ RationalNode (location: (2,0)-(2,3)) │ └── numeric: │ @ IntegerNode (location: (2,0)-(2,2)) @@ -18,8 +19,11 @@ │ ├── flags: decimal │ └── value: 1000 ├── @ FloatNode (location: (5,0)-(5,4)) + │ └── value: 10000000000.0 ├── @ FloatNode (location: (6,0)-(6,14)) + │ └── value: Infinity ├── @ FloatNode (location: (7,0)-(7,15)) + │ └── value: -Infinity ├── @ StringNode (location: (8,0)-(8,2)) │ ├── flags: ∅ │ ├── opening_loc: (8,0)-(8,1) = "?" @@ -58,7 +62,9 @@ │ │ └── unescaped: "baz" │ └── closing_loc: (11,13)-(11,14) = ")" ├── @ FloatNode (location: (12,0)-(12,16)) + │ └── value: Infinity ├── @ FloatNode (location: (13,0)-(13,17)) + │ └── value: -Infinity └── @ CallNode (location: (14,0)-(14,10)) ├── flags: ignore_visibility ├── receiver: ∅ diff --git a/test/prism/snapshots/whitequark/complex.txt b/test/prism/snapshots/whitequark/complex.txt index 80e7c00fb9d270..e688585a5f9f2f 100644 --- a/test/prism/snapshots/whitequark/complex.txt +++ b/test/prism/snapshots/whitequark/complex.txt @@ -6,11 +6,13 @@ ├── @ ImaginaryNode (location: (1,0)-(1,5)) │ └── numeric: │ @ FloatNode (location: (1,0)-(1,4)) + │ └── value: 42.1 ├── @ ImaginaryNode (location: (3,0)-(3,6)) │ └── numeric: │ @ RationalNode (location: (3,0)-(3,5)) │ └── numeric: │ @ FloatNode (location: (3,0)-(3,4)) + │ └── value: 42.1 ├── @ ImaginaryNode (location: (5,0)-(5,3)) │ └── numeric: │ @ IntegerNode (location: (5,0)-(5,2)) diff --git a/test/prism/snapshots/whitequark/float.txt b/test/prism/snapshots/whitequark/float.txt index 14457fcff27890..5e6a597db7deba 100644 --- a/test/prism/snapshots/whitequark/float.txt +++ b/test/prism/snapshots/whitequark/float.txt @@ -4,4 +4,6 @@ @ StatementsNode (location: (1,0)-(3,4)) └── body: (length: 2) ├── @ FloatNode (location: (1,0)-(1,5)) + │ └── value: -1.33 └── @ FloatNode (location: (3,0)-(3,4)) + └── value: 1.33 diff --git a/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt b/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt index e5b953b9fd27ff..afddc9cd3c6543 100644 --- a/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt +++ b/test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt @@ -22,6 +22,7 @@ │ │ │ │ @ StatementsNode (location: (1,5)-(1,9)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ FloatNode (location: (1,5)-(1,9)) + │ │ │ │ └── value: -1.3 │ │ │ ├── opening_loc: (1,4)-(1,5) = "(" │ │ │ └── closing_loc: (1,9)-(1,10) = ")" │ │ ├── call_operator_loc: (1,10)-(1,11) = "." @@ -52,6 +53,7 @@ │ │ │ @ StatementsNode (location: (3,6)-(3,10)) │ │ │ └── body: (length: 1) │ │ │ └── @ FloatNode (location: (3,6)-(3,10)) + │ │ │ └── value: -1.3 │ │ ├── opening_loc: (3,5)-(3,6) = "(" │ │ └── closing_loc: (3,10)-(3,11) = ")" │ ├── call_operator_loc: (3,11)-(3,12) = "." diff --git a/test/prism/snapshots/whitequark/rational.txt b/test/prism/snapshots/whitequark/rational.txt index 8b2cc17efdb24f..90bbd17929b031 100644 --- a/test/prism/snapshots/whitequark/rational.txt +++ b/test/prism/snapshots/whitequark/rational.txt @@ -6,6 +6,7 @@ ├── @ RationalNode (location: (1,0)-(1,5)) │ └── numeric: │ @ FloatNode (location: (1,0)-(1,4)) + │ └── value: 42.1 └── @ RationalNode (location: (3,0)-(3,3)) └── numeric: @ IntegerNode (location: (3,0)-(3,2)) diff --git a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt index 320958c9d43a96..93418e64483f98 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt @@ -109,6 +109,7 @@ │ │ │ ├── closing_loc: (3,7)-(3,8) = ")" │ │ │ └── block: ∅ │ │ └── @ FloatNode (location: (3,10)-(3,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (3,14)-(3,20)) @@ -167,6 +168,7 @@ │ │ └── @ ImaginaryNode (location: (5,10)-(5,14)) │ │ └── numeric: │ │ @ FloatNode (location: (5,10)-(5,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (5,15)-(5,21)) @@ -225,6 +227,7 @@ │ │ └── @ RationalNode (location: (7,10)-(7,14)) │ │ └── numeric: │ │ @ FloatNode (location: (7,10)-(7,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (7,15)-(7,21)) @@ -400,6 +403,7 @@ │ │ │ ├── closing_loc: (13,8)-(13,9) = ")" │ │ │ └── block: ∅ │ │ └── @ FloatNode (location: (13,11)-(13,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (13,15)-(13,21)) @@ -458,6 +462,7 @@ │ │ └── @ ImaginaryNode (location: (15,11)-(15,15)) │ │ └── numeric: │ │ @ FloatNode (location: (15,11)-(15,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (15,16)-(15,22)) @@ -516,6 +521,7 @@ │ │ └── @ RationalNode (location: (17,11)-(17,15)) │ │ └── numeric: │ │ @ FloatNode (location: (17,11)-(17,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (17,16)-(17,22)) @@ -701,6 +707,7 @@ │ │ │ ├── opening_loc: (23,3)-(23,4) = "{" │ │ │ └── closing_loc: (23,7)-(23,8) = "}" │ │ └── @ FloatNode (location: (23,10)-(23,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (23,14)-(23,20)) @@ -764,6 +771,7 @@ │ │ └── @ ImaginaryNode (location: (25,10)-(25,14)) │ │ └── numeric: │ │ @ FloatNode (location: (25,10)-(25,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (25,15)-(25,21)) @@ -827,6 +835,7 @@ │ │ └── @ RationalNode (location: (27,10)-(27,14)) │ │ └── numeric: │ │ @ FloatNode (location: (27,10)-(27,13)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (27,15)-(27,21)) @@ -1017,6 +1026,7 @@ │ │ │ ├── opening_loc: (33,3)-(33,4) = "{" │ │ │ └── closing_loc: (33,8)-(33,9) = "}" │ │ └── @ FloatNode (location: (33,11)-(33,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (33,15)-(33,21)) @@ -1080,6 +1090,7 @@ │ │ └── @ ImaginaryNode (location: (35,11)-(35,15)) │ │ └── numeric: │ │ @ FloatNode (location: (35,11)-(35,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (35,16)-(35,22)) @@ -1143,6 +1154,7 @@ │ │ └── @ RationalNode (location: (37,11)-(37,15)) │ │ └── numeric: │ │ @ FloatNode (location: (37,11)-(37,14)) + │ │ └── value: 1.0 │ ├── closing_loc: ∅ │ └── block: │ @ BlockNode (location: (37,16)-(37,22)) diff --git a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt index 75be379e2e4a5e..e14b0567e746a3 100644 --- a/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt +++ b/test/prism/snapshots/whitequark/unary_num_pow_precedence.txt @@ -7,6 +7,7 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ FloatNode (location: (1,0)-(1,4)) + │ │ └── value: 2.0 │ ├── call_operator_loc: ∅ │ ├── name: :** │ ├── message_loc: (1,5)-(1,7) = "**" @@ -56,6 +57,7 @@ │ ├── flags: ∅ │ ├── receiver: │ │ @ FloatNode (location: (5,1)-(5,4)) + │ │ └── value: 2.0 │ ├── call_operator_loc: ∅ │ ├── name: :** │ ├── message_loc: (5,5)-(5,7) = "**" From 40165354045613441adfab40bcec61b358cdae78 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 22 Feb 2024 20:22:47 -0500 Subject: [PATCH 013/147] [PRISM] Integrate new number parsing --- common.mk | 37 +++++++++++++++++ prism_compile.c | 104 +++++++++++++++++++++++------------------------- 2 files changed, 87 insertions(+), 54 deletions(-) diff --git a/common.mk b/common.mk index e35f8a84f96b3c..60c2a9a12a85b8 100644 --- a/common.mk +++ b/common.mk @@ -100,6 +100,7 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \ prism/util/pm_buffer.$(OBJEXT) \ prism/util/pm_char.$(OBJEXT) \ prism/util/pm_constant_pool.$(OBJEXT) \ + prism/util/pm_integer.$(OBJEXT) \ prism/util/pm_list.$(OBJEXT) \ prism/util/pm_memchr.$(OBJEXT) \ prism/util/pm_newline_list.$(OBJEXT) \ @@ -2244,6 +2245,7 @@ ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -2679,6 +2681,7 @@ builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -3311,6 +3314,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -3773,6 +3777,7 @@ cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -6742,6 +6747,7 @@ eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -7221,6 +7227,7 @@ gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -7476,6 +7483,7 @@ goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -7718,6 +7726,7 @@ hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -8752,6 +8761,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -9007,6 +9017,7 @@ load.$(OBJEXT): $(top_srcdir)/prism/regexp.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -10336,6 +10347,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -11917,6 +11929,7 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12111,6 +12124,7 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12291,6 +12305,7 @@ prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/diagnostic.$(OBJEXT): {$(VPATH)}config.h @@ -12317,6 +12332,7 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12505,6 +12521,7 @@ prism/node.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h @@ -12531,6 +12548,7 @@ prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h @@ -12553,6 +12571,7 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12572,6 +12591,7 @@ prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12594,6 +12614,7 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12608,6 +12629,7 @@ prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/token_type.$(OBJEXT): {$(VPATH)}config.h prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h @@ -12627,6 +12649,9 @@ prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.c prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/util/pm_constant_pool.$(OBJEXT): {$(VPATH)}config.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h @@ -12670,6 +12695,7 @@ prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h @@ -12695,6 +12721,7 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -12910,6 +12937,7 @@ proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -15392,6 +15420,7 @@ rjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -15644,6 +15673,7 @@ rjit_c.$(OBJEXT): $(top_srcdir)/prism/regexp.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -15922,6 +15952,7 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -18362,6 +18393,7 @@ thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -19622,6 +19654,7 @@ vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -19879,6 +19912,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -20108,6 +20142,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -20548,6 +20583,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -20988,6 +21024,7 @@ yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h diff --git a/prism_compile.c b/prism_compile.c index 565db1307c2c98..06dd2a1f0e119a 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -118,61 +118,51 @@ pm_node_line_number(const pm_parser_t *parser, const pm_node_t *node) return (int) pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line; } +/** + * Convert the value of an integer node into a Ruby Integer. + */ static VALUE parse_integer(const pm_integer_node_t *node) { - char *start = (char *) node->base.location.start; - char *end = (char *) node->base.location.end; + const pm_integer_t *integer = &node->value; - size_t length = end - start; - int base = -10; + VALUE result = UINT2NUM(integer->head.value); + size_t shift = 0; - switch (node->base.flags & (PM_INTEGER_BASE_FLAGS_BINARY | PM_INTEGER_BASE_FLAGS_DECIMAL | PM_INTEGER_BASE_FLAGS_OCTAL | PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) { - case PM_INTEGER_BASE_FLAGS_BINARY: - base = 2; - break; - case PM_INTEGER_BASE_FLAGS_DECIMAL: - base = 10; - break; - case PM_INTEGER_BASE_FLAGS_OCTAL: - base = 8; - break; - case PM_INTEGER_BASE_FLAGS_HEXADECIMAL: - base = 16; - break; - default: - rb_bug("Unreachable"); + for (pm_integer_word_t *node = integer->head.next; node != NULL; node = node->next) { + VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); + result = rb_funcall(receiver, rb_intern("|"), 1, result); } - return rb_int_parse_cstr(start, length, &end, NULL, base, RB_INT_PARSE_DEFAULT); + if (integer->negative) result = rb_funcall(result, rb_intern("-@"), 0); + return result; } +/** + * Convert the value of a float node into a Ruby Float. + */ static VALUE -parse_float(const pm_node_t *node) +parse_float(const pm_float_node_t *node) { - const uint8_t *start = node->location.start; - const uint8_t *end = node->location.end; - size_t length = end - start; - - char *buffer = malloc(length + 1); - memcpy(buffer, start, length); - - buffer[length] = '\0'; - VALUE number = DBL2NUM(rb_cstr_to_dbl(buffer, 0)); - - free(buffer); - return number; + return DBL2NUM(node->value); } +/** + * Convert the value of a rational node into a Ruby Rational. Rational nodes can + * either be wrapping an integer node or a float node. If it's an integer node, + * we can reuse our parsing. If it's not, then we'll parse the numerator and + * then parse the denominator and create the rational from those two values. + */ static VALUE -parse_rational(const pm_node_t *node) +parse_rational(const pm_rational_node_t *node) { - const uint8_t *start = node->location.start; - const uint8_t *end = node->location.end - 1; - size_t length = end - start; + VALUE result; + + if (PM_NODE_TYPE_P(node->numeric, PM_FLOAT_NODE)) { + const uint8_t *start = node->base.location.start; + const uint8_t *end = node->base.location.end - 1; + size_t length = end - start; - VALUE res; - if (PM_NODE_TYPE_P(((pm_rational_node_t *)node)->numeric, PM_FLOAT_NODE)) { char *buffer = malloc(length + 1); memcpy(buffer, start, length); @@ -184,35 +174,41 @@ parse_rational(const pm_node_t *node) size_t fraclen = length - seen_decimal - 1; memmove(decimal, decimal + 1, fraclen + 1); - VALUE v = rb_cstr_to_inum(buffer, 10, false); - res = rb_rational_new(v, rb_int_positive_pow(10, fraclen)); + VALUE numerator = rb_cstr_to_inum(buffer, 10, false); + result = rb_rational_new(numerator, rb_int_positive_pow(10, fraclen)); free(buffer); } else { - RUBY_ASSERT(PM_NODE_TYPE_P(((pm_rational_node_t *)node)->numeric, PM_INTEGER_NODE)); - VALUE number = rb_int_parse_cstr((const char *)start, length, NULL, NULL, -10, RB_INT_PARSE_DEFAULT); - res = rb_rational_raw(number, INT2FIX(1)); + RUBY_ASSERT(PM_NODE_TYPE_P(node->numeric, PM_INTEGER_NODE)); + VALUE numerator = parse_integer((const pm_integer_node_t *) node->numeric); + result = rb_rational_raw(numerator, INT2FIX(1)); } - return res; + return result; } +/** + * Convert the value of an imaginary node into a Ruby Complex. Imaginary nodes + * can be wrapping an integer node, a float node, or a rational node. In all + * cases we will reuse parsing functions seen above to get the inner value, and + * then convert into an imaginary with rb_complex_raw. + */ static VALUE parse_imaginary(pm_imaginary_node_t *node) { VALUE imaginary_part; switch (PM_NODE_TYPE(node->numeric)) { case PM_FLOAT_NODE: { - imaginary_part = parse_float(node->numeric); + imaginary_part = parse_float((const pm_float_node_t *) node->numeric); break; } case PM_INTEGER_NODE: { - imaginary_part = parse_integer((pm_integer_node_t *) node->numeric); + imaginary_part = parse_integer((const pm_integer_node_t *) node->numeric); break; } case PM_RATIONAL_NODE: { - imaginary_part = parse_rational(node->numeric); + imaginary_part = parse_rational((const pm_rational_node_t *) node->numeric); break; } default: @@ -409,7 +405,7 @@ pm_static_literal_value(const pm_node_t *node, const pm_scope_node_t *scope_node case PM_FALSE_NODE: return Qfalse; case PM_FLOAT_NODE: - return parse_float(node); + return parse_float((const pm_float_node_t *) node); case PM_HASH_NODE: { pm_hash_node_t *cast = (pm_hash_node_t *) node; pm_node_list_t *elements = &cast->elements; @@ -432,11 +428,11 @@ pm_static_literal_value(const pm_node_t *node, const pm_scope_node_t *scope_node case PM_IMAGINARY_NODE: return parse_imaginary((pm_imaginary_node_t *) node); case PM_INTEGER_NODE: - return parse_integer((pm_integer_node_t *) node); + return parse_integer((const pm_integer_node_t *) node); case PM_NIL_NODE: return Qnil; case PM_RATIONAL_NODE: - return parse_rational(node); + return parse_rational((const pm_rational_node_t *) node); case PM_REGULAR_EXPRESSION_NODE: { pm_regular_expression_node_t *cast = (pm_regular_expression_node_t *) node; @@ -5474,7 +5470,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_FLOAT_NODE: { if (!popped) { - ADD_INSN1(ret, &dummy_line_node, putobject, parse_float(node)); + ADD_INSN1(ret, &dummy_line_node, putobject, parse_float((const pm_float_node_t *) node)); } return; } @@ -5919,7 +5915,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_INTEGER_NODE: { if (!popped) { - ADD_INSN1(ret, &dummy_line_node, putobject, parse_integer((pm_integer_node_t *) node)); + ADD_INSN1(ret, &dummy_line_node, putobject, parse_integer((const pm_integer_node_t *) node)); } return; } @@ -6623,7 +6619,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // 1r // ^^ if (!popped) { - PUSH_INSN1(ret, location, putobject, parse_rational(node)); + PUSH_INSN1(ret, location, putobject, parse_rational((const pm_rational_node_t *) node)); } return; } From a154ea0c91b64cd7fb4d56e7ea6840488a68cb1d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 22 Feb 2024 21:22:56 -0500 Subject: [PATCH 014/147] [ruby/prism] Ignore other ERANGE errors for floats https://github.com/ruby/prism/commit/4267161ca7 --- prism/defines.h | 12 ++++++++++++ prism/prism.c | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/prism/defines.h b/prism/defines.h index 0abfa86e6685fe..6c09f108c230a9 100644 --- a/prism/defines.h +++ b/prism/defines.h @@ -10,6 +10,7 @@ #define PRISM_DEFINES_H #include +#include #include #include #include @@ -113,4 +114,15 @@ # endif #endif +/** + * isinf on Windows is defined as accepting a float, but on POSIX systems it + * accepts a float, a double, or a long double. We want to mirror this behavior + * on windows. + */ +#ifdef _WIN32 +# include +# undef isinf +# define isinf(x) (sizeof(x) == sizeof(float) ? !_finitef(x) : !_finite(x)) +#endif + #endif diff --git a/prism/prism.c b/prism/prism.c index 4f268fc952be3f..afd7969ae1a93b 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3181,7 +3181,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { // If errno is set, then it should only be ERANGE. At this point we need to // check if it's infinity (it should be). - if (errno == ERANGE) { + if (errno == ERANGE && isinf(value)) { int warn_width; const char *ellipsis; @@ -3194,7 +3194,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) { } pm_diagnostic_list_append_format(&parser->warning_list, token->start, token->end, PM_WARN_FLOAT_OUT_OF_RANGE, warn_width, (const char *) token->start, ellipsis); - value = (value < 0x0) ? -HUGE_VAL : HUGE_VAL; + value = (value < 0.0) ? -HUGE_VAL : HUGE_VAL; } // Finally we can free the buffer and return the value. From f403660805bafd86d4ff8c56094af8d48f58a24d Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 22 Feb 2024 20:55:31 -0800 Subject: [PATCH 015/147] Fallback more macos-arm-oss jobs to macos-14 A follow-up on https://github.com/ruby/ruby/pull/10074 --- .github/workflows/yjit-macos.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index de585e558da0a5..2637f9fd23a7de 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -64,11 +64,10 @@ jobs: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} RUN_OPTS: ${{ matrix.yjit_opts }} - runs-on: macos-arm-oss + runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} if: >- - ${{github.repository == 'ruby/ruby' && - !(false + ${{!(false || contains(github.event.head_commit.message, '[DOC]') || contains(github.event.pull_request.title, '[DOC]') || contains(github.event.pull_request.labels.*.name, 'Documentation') @@ -136,9 +135,9 @@ jobs: if: ${{ failure() }} result: - if: ${{ always() && github.repository == 'ruby/ruby' }} + if: ${{ always() }} name: ${{ github.workflow }} result - runs-on: macos-arm-oss + runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} needs: [make] steps: - run: exit 1 From 37dde6e2f82304848636015c0ce032cbdb5cd2a9 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Fri, 23 Feb 2024 18:02:14 +0800 Subject: [PATCH 016/147] [ruby/irb] Unroll extension method generation (https://github.com/ruby/irb/pull/882) * Unroll extension method generation Given we only have 2 remaining extension setter methods, both of which only take 1 argument and don't have any alias, the current method generation logic is overly complicated. This commit simplifies the method generation logic by simply defining the methods directly in the `IRB::Context` class. * Fix use_loader extension https://github.com/ruby/irb/commit/67eba5401b --- lib/irb/command.rb | 40 --------------------------------------- lib/irb/context.rb | 12 ++++++++++++ lib/irb/ext/use-loader.rb | 4 ++-- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/lib/irb/command.rb b/lib/irb/command.rb index c84474e633a4f8..83ec3b1b43d0a0 100644 --- a/lib/irb/command.rb +++ b/lib/irb/command.rb @@ -315,44 +315,4 @@ def self.extend_object(obj) install_extend_commands end - - # Extends methods for the Context module - module ContextExtender - CE = ContextExtender # :nodoc: - - @EXTEND_COMMANDS = [ - [:eval_history=, "ext/eval_history.rb"], - [:use_loader=, "ext/use-loader.rb"], - ] - - # Installs the default context extensions as irb commands: - # - # Context#eval_history=:: +irb/ext/history.rb+ - # Context#use_tracer=:: +irb/ext/tracer.rb+ - # Context#use_loader=:: +irb/ext/use-loader.rb+ - def self.install_extend_commands - for args in @EXTEND_COMMANDS - def_extend_command(*args) - end - end - - # Evaluate the given +command+ from the given +load_file+ on the Context - # module. - # - # Will also define any given +aliases+ for the method. - def self.def_extend_command(cmd_name, load_file, *aliases) - line = __LINE__; Context.module_eval %[ - def #{cmd_name}(*opts, &b) - Context.module_eval {remove_method(:#{cmd_name})} - require_relative "#{load_file}" - __send__ :#{cmd_name}, *opts, &b - end - for ali in aliases - alias_method ali, cmd_name - end - ], __FILE__, line - end - - CE.install_extend_commands - end end diff --git a/lib/irb/context.rb b/lib/irb/context.rb index e50958978fdc77..8eef3dff462f95 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -166,6 +166,18 @@ def use_tracer=(val) IRB.conf[:USE_TRACER] = val end + def eval_history=(val) + self.class.remove_method(__method__) + require_relative "ext/eval_history" + __send__(__method__, val) + end + + def use_loader=(val) + self.class.remove_method(__method__) + require_relative "ext/use-loader" + __send__(__method__, val) + end + private def build_completor completor_type = IRB.conf[:COMPLETOR] case completor_type diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb index c5ecbe28471e13..b22e6d2bf40614 100644 --- a/lib/irb/ext/use-loader.rb +++ b/lib/irb/ext/use-loader.rb @@ -4,7 +4,7 @@ # by Keiju ISHITSUKA(keiju@ruby-lang.org) # -require_relative "../cmd/load" +require_relative "../command/load" require_relative "loader" class Object @@ -49,7 +49,7 @@ def use_loader=(opt) if IRB.conf[:USE_LOADER] != opt IRB.conf[:USE_LOADER] = opt if opt - if !$".include?("irb/cmd/load") + if !$".include?("irb/command/load") end (class<<@workspace.main;self;end).instance_eval { alias_method :load, :irb_load From 4831bb5babb0743dce7aa6db6c2258d62ff962af Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Fri, 23 Feb 2024 18:53:50 +0800 Subject: [PATCH 017/147] [ruby/irb] Turn on frozen literal in files (https://github.com/ruby/irb/pull/881) https://github.com/ruby/irb/commit/83d90550c2 --- lib/irb/command.rb | 2 +- lib/irb/command/base.rb | 2 +- lib/irb/command/chws.rb | 2 +- lib/irb/command/irb_info.rb | 2 +- lib/irb/command/load.rb | 2 +- lib/irb/command/pushws.rb | 2 +- lib/irb/command/subirb.rb | 2 +- lib/irb/completion.rb | 2 +- lib/irb/context.rb | 2 +- lib/irb/ext/change-ws.rb | 2 +- lib/irb/ext/eval_history.rb | 2 +- lib/irb/ext/loader.rb | 2 +- lib/irb/ext/multi-irb.rb | 2 +- lib/irb/ext/tracer.rb | 2 +- lib/irb/ext/use-loader.rb | 2 +- lib/irb/ext/workspaces.rb | 2 +- lib/irb/frame.rb | 2 +- lib/irb/help.rb | 2 +- lib/irb/init.rb | 2 +- lib/irb/input-method.rb | 2 +- lib/irb/lc/error.rb | 2 +- lib/irb/lc/ja/error.rb | 2 +- lib/irb/locale.rb | 2 +- lib/irb/notifier.rb | 2 +- lib/irb/output-method.rb | 2 +- lib/irb/ruby-lex.rb | 2 +- lib/irb/version.rb | 2 +- lib/irb/workspace.rb | 2 +- lib/irb/ws-for-case-2.rb | 2 +- lib/irb/xmp.rb | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/irb/command.rb b/lib/irb/command.rb index 83ec3b1b43d0a0..4dc2994ba9d1f8 100644 --- a/lib/irb/command.rb +++ b/lib/irb/command.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/command.rb - irb command # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/command/base.rb b/lib/irb/command/base.rb index 880b781a46588f..3ce4f4d6c19922 100644 --- a/lib/irb/command/base.rb +++ b/lib/irb/command/base.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # nop.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/command/chws.rb b/lib/irb/command/chws.rb index 341d51615510f9..e1047686c520cf 100644 --- a/lib/irb/command/chws.rb +++ b/lib/irb/command/chws.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # change-ws.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/command/irb_info.rb b/lib/irb/command/irb_info.rb index 7fd3e2104abc1a..00ce7a5f066e20 100644 --- a/lib/irb/command/irb_info.rb +++ b/lib/irb/command/irb_info.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true module IRB # :stopdoc: diff --git a/lib/irb/command/load.rb b/lib/irb/command/load.rb index 0558bc83b01b3f..9e89a7b7f35751 100644 --- a/lib/irb/command/load.rb +++ b/lib/irb/command/load.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # load.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/command/pushws.rb b/lib/irb/command/pushws.rb index a6fcd6a1658592..fadd10d6aa4df3 100644 --- a/lib/irb/command/pushws.rb +++ b/lib/irb/command/pushws.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # change-ws.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/command/subirb.rb b/lib/irb/command/subirb.rb index 0a75706f5fe4c4..5cc7b8c6f85fa2 100644 --- a/lib/irb/command/subirb.rb +++ b/lib/irb/command/subirb.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # multi.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index 7b9c1bbbdd0707..ceb6eb087a1c56 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/completion.rb - # by Keiju ISHITSUKA(keiju@ishitsuka.com) diff --git a/lib/irb/context.rb b/lib/irb/context.rb index 8eef3dff462f95..d2d0bed522c6db 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/context.rb - irb context # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb index c0f810a4c80b06..ec29f7a2bc78cb 100644 --- a/lib/irb/ext/change-ws.rb +++ b/lib/irb/ext/change-ws.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/ext/cb.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/eval_history.rb b/lib/irb/ext/eval_history.rb index 1a04178b4080db..316e0b312e8ef8 100644 --- a/lib/irb/ext/eval_history.rb +++ b/lib/irb/ext/eval_history.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # history.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb index 5bd25546fab229..df5aaa8e5a1693 100644 --- a/lib/irb/ext/loader.rb +++ b/lib/irb/ext/loader.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # loader.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb index 1c20489137bd6c..944c04c822c9f3 100644 --- a/lib/irb/ext/multi-irb.rb +++ b/lib/irb/ext/multi-irb.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/multi-irb.rb - multiple irb module # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb index d498b5320b91ce..fd6daa88ae57b4 100644 --- a/lib/irb/ext/tracer.rb +++ b/lib/irb/ext/tracer.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/lib/tracer.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb index b22e6d2bf40614..f47d1cab048534 100644 --- a/lib/irb/ext/use-loader.rb +++ b/lib/irb/ext/use-loader.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # use-loader.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb index 9defc3e17bc530..f447948fbd44b4 100644 --- a/lib/irb/ext/workspaces.rb +++ b/lib/irb/ext/workspaces.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # push-ws.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb index 14768bd8f6bba5..4b697c8719e94e 100644 --- a/lib/irb/frame.rb +++ b/lib/irb/frame.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # frame.rb - # by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd) diff --git a/lib/irb/help.rb b/lib/irb/help.rb index 6861d7efc870a5..c97656f0c47013 100644 --- a/lib/irb/help.rb +++ b/lib/irb/help.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/help.rb - print usage module # by Keiju ISHITSUKA(keiju@ishitsuka.com) diff --git a/lib/irb/init.rb b/lib/irb/init.rb index 8acfdea8e197fc..107cba592915a0 100644 --- a/lib/irb/init.rb +++ b/lib/irb/init.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/init.rb - irb initialize module # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index c0e6c7e38bf702..a483ec671b044f 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/input-method.rb - input methods used irb # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb index 25f4ba2e1cd382..9041ec4d6c8b7d 100644 --- a/lib/irb/lc/error.rb +++ b/lib/irb/lc/error.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/lc/error.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb index 756b8b9afb2308..f7f2b13c45ca1e 100644 --- a/lib/irb/lc/ja/error.rb +++ b/lib/irb/lc/ja/error.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/lc/ja/error.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb index 1510af2ab48689..2abcc7354b7a23 100644 --- a/lib/irb/locale.rb +++ b/lib/irb/locale.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/locale.rb - internationalization module # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb index 612de3df168084..dc1b9ef14b0675 100644 --- a/lib/irb/notifier.rb +++ b/lib/irb/notifier.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # notifier.rb - output methods used by irb # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb index 06fd37157ce0ba..69942f47a28af2 100644 --- a/lib/irb/output-method.rb +++ b/lib/irb/output-method.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # output-method.rb - output methods used by irb # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 754acfad05aec2..cfe36be83f7b31 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/ruby-lex.rb - ruby lexcal analyzer # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/version.rb b/lib/irb/version.rb index 585c8370208633..d9753d3eb63a8a 100644 --- a/lib/irb/version.rb +++ b/lib/irb/version.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/version.rb - irb version definition file # by Keiju ISHITSUKA(keiju@ishitsuka.com) diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb index aaf2f335e227b4..4c3b5e425e1183 100644 --- a/lib/irb/workspace.rb +++ b/lib/irb/workspace.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/workspace-binding.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb index a0f617e4ed0c80..03f42d73d974a5 100644 --- a/lib/irb/ws-for-case-2.rb +++ b/lib/irb/ws-for-case-2.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/ws-for-case-2.rb - # by Keiju ISHITSUKA(keiju@ruby-lang.org) diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb index de29089429b3d6..b1bc53283e88ec 100644 --- a/lib/irb/xmp.rb +++ b/lib/irb/xmp.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # xmp.rb - irb version of gotoken xmp # by Keiju ISHITSUKA(Nippon Rational Inc.) From 41c0fb699139f82c92414638a7b31565d9841f1c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 21 Feb 2024 13:42:11 +0900 Subject: [PATCH 018/147] [ruby/optparse] Add `exact:` keyword argument https://github.com/ruby/optparse/commit/07e83673a8 --- lib/optparse.rb | 58 +++++++++++++++++----------------- test/optparse/test_optparse.rb | 29 +++++++++++++++++ 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 2ee592954c78ea..08abca220f14e2 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1654,21 +1654,21 @@ def separator(string) # # Returns the rest of +argv+ left unparsed. # - def order(*argv, into: nil, &nonopt) + def order(*argv, **keywords, &nonopt) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - order!(argv, into: into, &nonopt) + order!(argv, **keywords, &nonopt) end # # Same as #order, but removes switches destructively. # Non-option arguments remain in +argv+. # - def order!(argv = default_argv, into: nil, &nonopt) + def order!(argv = default_argv, into: nil, **keywords, &nonopt) setter = ->(name, val) {into[name.to_sym] = val} if into - parse_in_order(argv, setter, &nonopt) + parse_in_order(argv, setter, **keywords, &nonopt) end - def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: + def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc: opt, arg, val, rest = nil nonopt ||= proc {|a| throw :terminate, a} argv.unshift(arg) if arg = catch(:terminate) { @@ -1679,7 +1679,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: opt, rest = $1, $2 opt.tr!('_', '-') begin - if require_exact + if exact sw, = search(:long, opt) else sw, = complete(:long, opt, true) @@ -1714,7 +1714,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: val = arg.delete_prefix('-') has_arg = true rescue InvalidOption - raise if require_exact + raise if exact # if no short options match, try completion with long # options. sw, = complete(:long, opt) @@ -1779,18 +1779,18 @@ def callback!(cb, max_arity, *args) # :nodoc: # []= method (so it can be Hash, or OpenStruct, or other # similar object). # - def permute(*argv, into: nil) + def permute(*argv, **keywords) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - permute!(argv, into: into) + permute!(argv, **keywords) end # # Same as #permute, but removes switches destructively. # Non-option arguments remain in +argv+. # - def permute!(argv = default_argv, into: nil) + def permute!(argv = default_argv, **keywords) nonopts = [] - order!(argv, into: into, &nonopts.method(:<<)) + order!(argv, **keywords, &nonopts.method(:<<)) argv[0, 0] = nonopts argv end @@ -1802,20 +1802,20 @@ def permute!(argv = default_argv, into: nil) # values are stored there via []= method (so it can be Hash, # or OpenStruct, or other similar object). # - def parse(*argv, into: nil) + def parse(*argv, **keywords) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - parse!(argv, into: into) + parse!(argv, **keywords) end # # Same as #parse, but removes switches destructively. # Non-option arguments remain in +argv+. # - def parse!(argv = default_argv, into: nil) + def parse!(argv = default_argv, **keywords) if ENV.include?('POSIXLY_CORRECT') - order!(argv, into: into) + order!(argv, **keywords) else - permute!(argv, into: into) + permute!(argv, **keywords) end end @@ -1838,7 +1838,7 @@ def parse!(argv = default_argv, into: nil) # # params[:bar] = "x" # --bar x # # params[:zot] = "z" # --zot Z # - def getopts(*args, symbolize_names: false) + def getopts(*args, symbolize_names: false, **keywords) argv = Array === args.first ? args.shift : default_argv single_options, *long_options = *args @@ -1866,7 +1866,7 @@ def getopts(*args, symbolize_names: false) end end - parse_in_order(argv, result.method(:[]=)) + parse_in_order(argv, result.method(:[]=), **keywords) symbolize_names ? result.transform_keys(&:to_sym) : result end @@ -1979,10 +1979,10 @@ def candidate(word) # The optional +into+ keyword argument works exactly like that accepted in # method #parse. # - def load(filename = nil, into: nil) + def load(filename = nil, **keywords) unless filename basename = File.basename($0, '.*') - return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil + return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil basename << ".options" return [ # XDG @@ -1994,11 +1994,11 @@ def load(filename = nil, into: nil) '~/config/settings', ].any? {|dir| next if !dir or dir.empty? - load(File.expand_path(basename, dir), into: into) rescue nil + load(File.expand_path(basename, dir), **keywords) rescue nil } end begin - parse(*File.readlines(filename, chomp: true), into: into) + parse(*File.readlines(filename, chomp: true), **keywords) true rescue Errno::ENOENT, Errno::ENOTDIR false @@ -2011,10 +2011,10 @@ def load(filename = nil, into: nil) # # +env+ defaults to the basename of the program. # - def environment(env = File.basename($0, '.*')) + def environment(env = File.basename($0, '.*'), **keywords) env = ENV[env] || ENV[env.upcase] or return require 'shellwords' - parse(*Shellwords.shellwords(env)) + parse(*Shellwords.shellwords(env), **keywords) end # @@ -2331,19 +2331,19 @@ def options # Parses +self+ destructively in order and returns +self+ containing the # rest arguments left unparsed. # - def order!(&blk) options.order!(self, &blk) end + def order!(**keywords, &blk) options.order!(self, **keywords, &blk) end # # Parses +self+ destructively in permutation mode and returns +self+ # containing the rest arguments left unparsed. # - def permute!() options.permute!(self) end + def permute!(**keywords) options.permute!(self, **keywords) end # # Parses +self+ destructively and returns +self+ containing the # rest arguments left unparsed. # - def parse!() options.parse!(self) end + def parse!(**keywords) options.parse!(self, **keywords) end # # Substitution of getopts is possible as follows. Also see @@ -2356,8 +2356,8 @@ def parse!() options.parse!(self) end # rescue OptionParser::ParseError # end # - def getopts(*args, symbolize_names: false) - options.getopts(self, *args, symbolize_names: symbolize_names) + def getopts(*args, symbolize_names: false, **keywords) + options.getopts(self, *args, symbolize_names: symbolize_names, **keywords) end # diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb index 3b9ccc756ace06..393b0334b136df 100644 --- a/test/optparse/test_optparse.rb +++ b/test/optparse/test_optparse.rb @@ -116,6 +116,35 @@ def test_require_exact assert_equal(false, @foo) end + def test_exact_option + @opt.def_option('-F', '--zrs=IRS', 'zrs') + %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg| + result = {} + @opt.parse([arg, 'foo'], into: result) + assert_equal({zrs: 'foo'}, result) + end + + [%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args| + result = {} + @opt.parse(args, into: result, exact: true) + assert_equal({zrs: 'foo'}, result) + end + + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo), exact: true)} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo), exact: true)} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo), exact: true)} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo), exact: true)} + assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo), exact: true)} + + @opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg} + @opt.parse(%w[-f], exact: true) + assert_equal(true, @foo) + @opt.parse(%w[--foo], exact: true) + assert_equal(true, @foo) + @opt.parse(%w[--no-foo], exact: true) + assert_equal(false, @foo) + end + def test_raise_unknown @opt.def_option('--my-foo [ARG]') {|arg| @foo = arg} assert @opt.raise_unknown From 598b03648f3277d65ab12a8cfb63222474788037 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Fri, 23 Feb 2024 21:32:47 +0900 Subject: [PATCH 019/147] [ruby/irb] Remove remaining `frozen_string_literal: false` in lib/ (https://github.com/ruby/irb/pull/883) https://github.com/ruby/irb/commit/4bfdb23ae6 --- lib/irb.rb | 8 ++++---- lib/irb/inspector.rb | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/irb.rb b/lib/irb.rb index 09ea9256cbe3e8..f5a7d24da7755f 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb.rb - irb main module # by Keiju ISHITSUKA(keiju@ruby-lang.org) @@ -903,8 +903,8 @@ class Irb # parsed as a :method_add_arg and the output won't be suppressed PROMPT_MAIN_TRUNCATE_LENGTH = 32 - PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze - CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze + PROMPT_MAIN_TRUNCATE_OMISSION = '...' + CONTROL_CHARACTERS_PATTERN = "\x00-\x1F" # Returns the current context of this irb session attr_reader :context @@ -1056,7 +1056,7 @@ def readmultiline return read_input(prompt) if @context.io.respond_to?(:check_termination) # nomultiline - code = '' + code = +'' line_offset = 0 loop do line = read_input(prompt) diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb index 7bdd855b9ab115..667087ccba3d72 100644 --- a/lib/irb/inspector.rb +++ b/lib/irb/inspector.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true # # irb/inspector.rb - inspect methods # by Keiju ISHITSUKA(keiju@ruby-lang.org) @@ -113,7 +113,7 @@ def inspect_value(v) Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v)) } Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v| - IRB::ColorPrinter.pp(v, '').chomp + IRB::ColorPrinter.pp(v, +'').chomp } Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v| begin From f0172fc7ee9f0c27cb543f52deae477c9ada4c79 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Fri, 23 Feb 2024 21:32:55 +0900 Subject: [PATCH 020/147] [ruby/irb] Remove workaround for empty lines in dynamic_prompt (https://github.com/ruby/irb/pull/884) https://github.com/ruby/irb/commit/820b9e8dd6 --- lib/irb.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/irb.rb b/lib/irb.rb index f5a7d24da7755f..55988858664ced 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -1138,7 +1138,6 @@ def configure_io 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, local_variables: @context.local_variables) line_results = IRB::NestingParser.parse_by_line(tokens) tokens_until_line = [] From 7da3f8dcd34a58ce806cf2d8b22edb3261dea131 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 23 Feb 2024 21:49:57 +0900 Subject: [PATCH 021/147] [ruby/optparse] [DOC] About return value of OptionParser#new https://github.com/ruby/optparse/commit/59b9fd7ddc --- lib/optparse.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 08abca220f14e2..51dbfd0ad2190e 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1216,9 +1216,9 @@ def self.accept(*args, &blk) top.accept(*args, &blk) end # # Directs to reject specified class argument. # - # +t+:: Argument class specifier, any object including Class. + # +type+:: Argument class specifier, any object including Class. # - # reject(t) + # reject(type) # def reject(*args, &blk) top.reject(*args, &blk) end # @@ -1347,6 +1347,9 @@ def base # # Pushes a new List. # + # If a block is given, yields +self+ and returns the result of the + # block, otherwise returns +self+. + # def new @stack.push(List.new) if block_given? @@ -1570,6 +1573,12 @@ def make_switch(opts, block = nil) nolong end + # ---- + # Option definition phase methods + # + # These methods are used to define options, or to construct an + # OptionParser instance in other words. + # :call-seq: # define(*params, &block) # @@ -1645,6 +1654,13 @@ def separator(string) top.append(string, nil, nil) end + # ---- + # Arguments parse phase methods + # + # These methods parse +argv+, convert, and store the results by + # calling handlers. As these methods do not modify +self+, +self+ + # can be frozen. + # # Parses command line arguments +argv+ in order. When a block is given, # each non-option argument is yielded. When optional +into+ keyword From 3371936b6f863ab0aae0ad5a106cad03b377b88e Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Wed, 31 Jan 2024 16:45:11 +0900 Subject: [PATCH 022/147] Add Launchable into CI --- .github/workflows/macos.yml | 71 ++++++- tool/lib/test/unit.rb | 330 ++++++++++++++++++++------------- tool/lib/test/unit/parallel.rb | 2 +- 3 files changed, 268 insertions(+), 135 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1f2b4ef585b9b3..b0d03547aae196 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -13,6 +13,21 @@ on: # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: +env: + # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App. + # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42 + GITHUB_PULL_REQUEST_URL: ${{ github.event.pull_request.html_url }} + # The following envs are necessary in Launchable tokenless authentication. + # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20 + LAUNCHABLE_ORGANIZATION: ${{ github.repository_owner }} + LAUNCHABLE_WORKSPACE: ${{ github.event.repository.name }} + # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71 + GITHUB_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + # This secret setting is needed if you want to run Launchable on your forked + # repository. + # See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details. + LAUNCHABLE_TOKEN: ${{ secrets.LAUNCHABLE_TOKEN }} + concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} @@ -25,12 +40,14 @@ jobs: strategy: matrix: test_task: ['check'] + test_opts: [''] os: - macos-12 - macos-13 - ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} include: - - test_task: test-all TESTS=--repeat-count=2 + - test_task: test-all + test_opts: --repeat-count=2 os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} - test_task: test-bundled-gems os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }} @@ -50,10 +67,23 @@ jobs: )}} steps: + - name: Enable Launchable conditionally + id: enable_launchable + run: echo "enable_launchable=true" >> $GITHUB_OUTPUT + working-directory: + if: >- + ${{ + (github.repository == 'ruby/ruby' || + (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)) && + (matrix.test_task == 'check' || matrix.test_task == 'test-all') + }} + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: sparse-checkout-cone-mode: false sparse-checkout: /.github + # Set fetch-depth: 0 so that Launchable can receive commits information. + fetch-depth: 0 - name: Install libraries uses: ./.github/actions/setup/macos @@ -80,6 +110,41 @@ jobs: echo "TESTS=${TESTS}" >> $GITHUB_ENV if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + # Launchable CLI requires Python and Java + # https://www.launchableinc.com/docs/resources/cli-reference/ + - name: Set up Python + uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 + with: + python-version: "3.10" + if: steps.enable_launchable.outputs.enable_launchable + + - name: Set up Java + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'temurin' + java-version: '17' + if: steps.enable_launchable.outputs.enable_launchable + + - name: Set up Launchable + run: | + set -x + pip install launchable + launchable verify + : # The build name cannot include a slash, so we replace the string here. + github_ref="$(echo ${{ github.ref }} | sed 's/\//_/g')" + : # With the --name option, we need to configure a unique identifier for this build. + : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here. + : # + : # FIXME: Need to fix `WARNING: Failed to process a change to a file`. + : # https://github.com/launchableinc/cli/issues/786 + launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA} + echo "TESTS=${TESTS} --launchable-test-reports=launchable_reports.json" >> $GITHUB_ENV + if: steps.enable_launchable.outputs.enable_launchable + + - name: Set extra test options + run: echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV + if: matrix.test_opts + - name: make ${{ matrix.test_task }} run: | make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} @@ -99,6 +164,10 @@ jobs: if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + - name: Launchable - record tests + run: launchable record tests --flavor os=${{ matrix.os }} --flavor test_task=${{ matrix.test_task }} raw launchable_reports.json + if: ${{ always() && steps.enable_launchable.outputs.enable_launchable }} + - uses: ./.github/actions/slack with: label: ${{ matrix.os }} / ${{ matrix.test_task }} diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index fc51e7e97c7699..a068ae6b9d44e4 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -842,7 +842,7 @@ def update_list(list, rec, max) end end - def record(suite, method, assertions, time, error) + def record(suite, method, assertions, time, error, source_location = nil) if @options.values_at(:longest, :most_asserted).any? @tops ||= {} rec = [suite.name, method, assertions, time, error] @@ -854,38 +854,6 @@ def record(suite, method, assertions, time, error) end end # (((@record ||= {})[suite] ||= {})[method]) = [assertions, time, error] - if writer = @options[:launchable_test_reports] - location = suite.instance_method(method).source_location - if location && path = location.first - # Launchable JSON schema is defined at - # https://github.com/search?q=repo%3Alaunchableinc%2Fcli+https%3A%2F%2Flaunchableinc.com%2Fschema%2FRecordTestInput&type=code. - e = case error - when nil - status = 'TEST_PASSED' - nil - when Test::Unit::PendedError - status = 'TEST_SKIPPED' - "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" - when Test::Unit::AssertionFailedError - status = 'TEST_FAILED' - "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n" - when Timeout::Error - status = 'TEST_FAILED' - "Timeout:\n#{klass}##{meth}\n" - else - status = 'TEST_FAILED' - bt = Test::filter_backtrace(e.backtrace).join "\n " - "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message.b}\n #{bt}\n" - end - writer.write_object do - writer.write_key_value('testPath', "file=#{path}#class=#{suite.name}#testcase=#{method}",) - writer.write_key_value('status', status) - writer.write_key_value('duration', time) - writer.write_key_value('createdAt', Time.now) - writer.write_key_value('stderr', e) if e - end - end - end super end @@ -914,104 +882,6 @@ def setup_options(opts, options) opts.on '--most-asserted=N', Integer, 'Show most asserted N tests' do |n| options[:most_asserted] = n end - opts.on '--launchable-test-reports=PATH', String, 'Report test results in Launchable JSON format' do |path| - require 'json' - options[:launchable_test_reports] = writer = JsonStreamWriter.new(path) - writer.write_array('testCases') - at_exit{ writer.close } - end - end - ## - # JsonStreamWriter writes a JSON file using a stream. - # By utilizing a stream, we can minimize memory usage, especially for large files. - class JsonStreamWriter - def initialize(path) - @file = File.open(path, "w") - @file.write("{") - @indent_level = 0 - @is_first_key_val = true - @is_first_obj = true - write_new_line - end - - def write_object - if @is_first_obj - @is_first_obj = false - else - write_comma - write_new_line - end - @indent_level += 1 - write_indent - @file.write("{") - write_new_line - @indent_level += 1 - yield - @indent_level -= 1 - write_new_line - write_indent - @file.write("}") - @indent_level -= 1 - @is_first_key_val = true - end - - def write_array(key) - @indent_level += 1 - write_indent - @file.write(to_json_str(key)) - write_colon - @file.write(" ", "[") - write_new_line - end - - def write_key_value(key, value) - if @is_first_key_val - @is_first_key_val = false - else - write_comma - write_new_line - end - write_indent - @file.write(to_json_str(key)) - write_colon - @file.write(" ") - @file.write(to_json_str(value)) - end - - def close - close_array - @indent_level -= 1 - write_new_line - @file.write("}") - end - - private - def to_json_str(obj) - JSON.dump(obj) - end - - def write_indent - @file.write(" " * 2 * @indent_level) - end - - def write_new_line - @file.write("\n") - end - - def write_comma - @file.write(',') - end - - def write_colon - @file.write(":") - end - - def close_array - write_new_line - write_indent - @file.write("]") - @indent_level -= 1 - end end end @@ -1483,6 +1353,198 @@ def non_options(files, options) end end + module LaunchableOption + module Nothing + private + def setup_options(opts, options) + super + opts.define_tail 'Launchable options:' + # This is expected to be called by Test::Unit::Worker. + opts.on_tail '--launchable-test-reports=PATH', String, 'Do nothing' + end + end + + def record(suite, method, assertions, time, error, source_location = nil) + if writer = @options[:launchable_test_reports] + if path = (source_location || suite.instance_method(method).source_location).first + # Launchable JSON schema is defined at + # https://github.com/search?q=repo%3Alaunchableinc%2Fcli+https%3A%2F%2Flaunchableinc.com%2Fschema%2FRecordTestInput&type=code. + e = case error + when nil + status = 'TEST_PASSED' + nil + when Test::Unit::PendedError + status = 'TEST_SKIPPED' + "Skipped:\n#{suite.name}##{method} [#{location error}]:\n#{error.message}\n" + when Test::Unit::AssertionFailedError + status = 'TEST_FAILED' + "Failure:\n#{suite.name}##{method} [#{location error}]:\n#{error.message}\n" + when Timeout::Error + status = 'TEST_FAILED' + "Timeout:\n#{suite.name}##{method}\n" + else + status = 'TEST_FAILED' + bt = Test::filter_backtrace(error.backtrace).join "\n " + "Error:\n#{suite.name}##{method}:\n#{error.class}: #{error.message.b}\n #{bt}\n" + end + repo_path = File.expand_path("#{__dir__}/../../../") + relative_path = path.delete_prefix("#{repo_path}/") + # The test path is a URL-encoded representation. + # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18 + test_path = {file: relative_path, class: suite.name, testcase: method}.map{|key, val| + "#{encode_test_path_component(key)}=#{encode_test_path_component(val)}" + }.join('#') + end + end + super + ensure + if writer && test_path && status + # Occasionally, the file writing operation may be paused, especially when `--repeat-count` is specified. + # In such cases, we proceed to execute the operation here. + writer.write_object do + writer.write_key_value('testPath', test_path) + writer.write_key_value('status', status) + writer.write_key_value('duration', time) + writer.write_key_value('createdAt', Time.now.to_s) + writer.write_key_value('stderr', e) + writer.write_key_value('stdout', nil) + end + end + end + + private + def setup_options(opts, options) + super + opts.on_tail '--launchable-test-reports=PATH', String, 'Report test results in Launchable JSON format' do |path| + require 'json' + require 'uri' + options[:launchable_test_reports] = writer = JsonStreamWriter.new(path) + writer.write_array('testCases') + main_pid = Process.pid + at_exit { + # This block is executed when the fork block in a test is completed. + # Therefore, we need to verify whether all tests have been completed. + stack = caller + if stack.size == 0 && main_pid == Process.pid && $!.is_a?(SystemExit) + writer.close + end + } + end + + def encode_test_path_component component + component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26') + end + end + + ## + # JsonStreamWriter writes a JSON file using a stream. + # By utilizing a stream, we can minimize memory usage, especially for large files. + class JsonStreamWriter + def initialize(path) + @file = File.open(path, "w") + @file.write("{") + @indent_level = 0 + @is_first_key_val = true + @is_first_obj = true + write_new_line + end + + def write_object + if @is_first_obj + @is_first_obj = false + else + write_comma + write_new_line + end + @indent_level += 1 + write_indent + @file.write("{") + write_new_line + @indent_level += 1 + yield + @indent_level -= 1 + write_new_line + write_indent + @file.write("}") + @indent_level -= 1 + @is_first_key_val = true + # Occasionally, invalid JSON will be created as shown below, especially when `--repeat-count` is specified. + # { + # "testPath": "file=test%2Ftest_timeout.rb&class=TestTimeout&testcase=test_allows_zero_seconds", + # "status": "TEST_PASSED", + # "duration": 2.7e-05, + # "createdAt": "2024-02-09 12:21:07 +0000", + # "stderr": null, + # "stdout": null + # }: null <- here + # }, + # To prevent this, IO#flush is called here. + @file.flush + end + + def write_array(key) + @indent_level += 1 + write_indent + @file.write(to_json_str(key)) + write_colon + @file.write(" ", "[") + write_new_line + end + + def write_key_value(key, value) + if @is_first_key_val + @is_first_key_val = false + else + write_comma + write_new_line + end + write_indent + @file.write(to_json_str(key)) + write_colon + @file.write(" ") + @file.write(to_json_str(value)) + end + + def close + return if @file.closed? + close_array + @indent_level -= 1 + write_new_line + @file.write("}") + @file.flush + @file.close + end + + private + def to_json_str(obj) + JSON.dump(obj) + end + + def write_indent + @file.write(" " * 2 * @indent_level) + end + + def write_new_line + @file.write("\n") + end + + def write_comma + @file.write(',') + end + + def write_colon + @file.write(":") + end + + def close_array + write_new_line + write_indent + @file.write("]") + @indent_level -= 1 + end + end + end + class Runner # :nodoc: all attr_accessor :report, :failures, :errors, :skips # :nodoc: @@ -1720,13 +1782,13 @@ def _end_method(inst) # failure or error in teardown, it will be sent again with the # error or failure. - def record suite, method, assertions, time, error + def record suite, method, assertions, time, error, source_location = nil end def location e # :nodoc: last_before_assertion = "" - return '' unless e.backtrace # SystemStackError can return nil. + return '' unless e&.backtrace # SystemStackError can return nil. e.backtrace.reverse_each do |s| break if s =~ /in .(?:Test::Unit::(?:Core)?Assertions#)?(assert|refute|flunk|pass|fail|raise|must|wont)/ @@ -1811,6 +1873,7 @@ def status io = self.output prepend Test::Unit::ExcludesOption prepend Test::Unit::TimeoutOption prepend Test::Unit::RunCount + prepend Test::Unit::LaunchableOption::Nothing ## # Begins the full test run. Delegates to +runner+'s #_run method. @@ -1867,6 +1930,7 @@ def puke klass, meth, e class AutoRunner # :nodoc: all class Runner < Test::Unit::Runner include Test::Unit::RequireFiles + include Test::Unit::LaunchableOption end attr_accessor :to_run, :options diff --git a/tool/lib/test/unit/parallel.rb b/tool/lib/test/unit/parallel.rb index f2244ec20aa385..ac297d4a0ec180 100644 --- a/tool/lib/test/unit/parallel.rb +++ b/tool/lib/test/unit/parallel.rb @@ -180,7 +180,7 @@ def record(suite, method, assertions, time, error) # :nodoc: else error = ProxyError.new(error) end - _report "record", Marshal.dump([suite.name, method, assertions, time, error]) + _report "record", Marshal.dump([suite.name, method, assertions, time, error, suite.instance_method(method).source_location]) super end end From ea2fb7460e8bb15d420cbcc50c2722eb3c302815 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Fri, 23 Feb 2024 22:11:16 +0900 Subject: [PATCH 023/147] [ruby/irb] Remove useless loaded file check (https://github.com/ruby/irb/pull/885) https://github.com/ruby/irb/commit/f6d489658e --- lib/irb/ext/use-loader.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb index f47d1cab048534..77c53b7d57d719 100644 --- a/lib/irb/ext/use-loader.rb +++ b/lib/irb/ext/use-loader.rb @@ -49,8 +49,6 @@ def use_loader=(opt) if IRB.conf[:USE_LOADER] != opt IRB.conf[:USE_LOADER] = opt if opt - if !$".include?("irb/command/load") - end (class<<@workspace.main;self;end).instance_eval { alias_method :load, :irb_load alias_method :require, :irb_require From 6bd3e8fbb2b0645f535858b3bd3bcb7242a6a438 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 17:02:36 -0500 Subject: [PATCH 024/147] Use rb_hash_foreach in coverage Using RHASH_TBL_RAW is a private API, so we should use rb_hash_foreach rather than RHASH_TBL_RAW with st_foreach. --- ext/coverage/coverage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c index a3381901ee4ad1..9fc93bb58d734c 100644 --- a/ext/coverage/coverage.c +++ b/ext/coverage/coverage.c @@ -353,7 +353,8 @@ rb_coverage_peek_result(VALUE klass) rb_raise(rb_eRuntimeError, "coverage measurement is not enabled"); } OBJ_WB_UNPROTECT(coverages); - st_foreach(RHASH_TBL_RAW(coverages), coverage_peek_result_i, ncoverages); + + rb_hash_foreach(coverages, coverage_peek_result_i, ncoverages); if (current_mode & COVERAGE_TARGET_METHODS) { rb_objspace_each_objects(method_coverage_i, &ncoverages); From 386a00663092fc5eff0770dcb4b4ce5d6797dd74 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 18:03:14 -0500 Subject: [PATCH 025/147] Use rb_hash_foreach in objspace.c Using RHASH_TBL_RAW is a private API, so we should use rb_hash_foreach rather than RHASH_TBL_RAW with st_foreach. --- ext/objspace/objspace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index 0a7896d5c63014..06fa5f9d225722 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -169,8 +169,7 @@ setup_hash(int argc, VALUE *argv) hash = rb_hash_new(); } else if (!RHASH_EMPTY_P(hash)) { - /* WB: no new reference */ - st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash); + rb_hash_foreach(hash, set_zero_i, (st_data_t)hash); } return hash; From df5b8ea4dbcc9a84969c4b941ffd0a5f468fd0fa Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 16:02:10 -0500 Subject: [PATCH 026/147] Remove unneeded RUBY_FUNC_EXPORTED --- array.c | 2 +- file.c | 2 +- hash.c | 2 +- io.c | 2 +- shape.c | 2 +- shape.h | 6 +++--- string.c | 2 +- variable.c | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/array.c b/array.c index aee8886e122091..a6cfd9bd22ad62 100644 --- a/array.c +++ b/array.c @@ -880,7 +880,7 @@ rb_ary_free(VALUE ary) } } -RUBY_FUNC_EXPORTED size_t +size_t rb_ary_memsize(VALUE ary) { if (ARY_OWNS_HEAP_P(ary)) { diff --git a/file.c b/file.c index 718ecaf2a009fe..2610449b4994fb 100644 --- a/file.c +++ b/file.c @@ -2463,7 +2463,7 @@ rb_file_ctime(VALUE obj) * */ -RUBY_FUNC_EXPORTED VALUE +VALUE rb_file_s_birthtime(VALUE klass, VALUE fname) { statx_data st; diff --git a/hash.c b/hash.c index c8fe54eff90fdc..fba394fc4003f4 100644 --- a/hash.c +++ b/hash.c @@ -1600,7 +1600,7 @@ rb_hash_modify_check(VALUE hash) rb_check_frozen(hash); } -RUBY_FUNC_EXPORTED struct st_table * +struct st_table * rb_hash_tbl_raw(VALUE hash, const char *file, int line) { return ar_force_convert_table(hash, file, line); diff --git a/io.c b/io.c index 94e6b506569222..b4488170eabe55 100644 --- a/io.c +++ b/io.c @@ -5622,7 +5622,7 @@ rb_io_fptr_finalize(rb_io_t *fptr) } #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr) -RUBY_FUNC_EXPORTED size_t +size_t rb_io_memsize(const rb_io_t *fptr) { size_t size = sizeof(rb_io_t); diff --git a/shape.c b/shape.c index 8d8314db331d44..06d0f2135d53cb 100644 --- a/shape.c +++ b/shape.c @@ -322,7 +322,7 @@ rb_shape_each_shape(each_shape_callback callback, void *data) } } -RUBY_FUNC_EXPORTED rb_shape_t* +RUBY_FUNC_EXPORTED rb_shape_t * rb_shape_get_shape_by_id(shape_id_t shape_id) { RUBY_ASSERT(shape_id != INVALID_SHAPE_ID); diff --git a/shape.h b/shape.h index 4fc46b452545a9..60e68dfe9b29c9 100644 --- a/shape.h +++ b/shape.h @@ -150,12 +150,12 @@ int32_t rb_shape_id_offset(void); rb_shape_t * rb_shape_get_parent(rb_shape_t * shape); -rb_shape_t* rb_shape_get_shape_by_id(shape_id_t shape_id); -shape_id_t rb_shape_get_shape_id(VALUE obj); +RUBY_FUNC_EXPORTED rb_shape_t *rb_shape_get_shape_by_id(shape_id_t shape_id); +RUBY_FUNC_EXPORTED shape_id_t rb_shape_get_shape_id(VALUE obj); rb_shape_t * rb_shape_get_next_iv_shape(rb_shape_t * shape, ID id); bool rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t * value); bool rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t * value, shape_id_t *shape_id_hint); -bool rb_shape_obj_too_complex(VALUE obj); +RUBY_FUNC_EXPORTED bool rb_shape_obj_too_complex(VALUE obj); void rb_shape_set_shape(VALUE obj, rb_shape_t* shape); rb_shape_t* rb_shape_get_shape(VALUE obj); diff --git a/string.c b/string.c index f8a64fca13c5e9..24dd29b32e2528 100644 --- a/string.c +++ b/string.c @@ -1578,7 +1578,7 @@ rb_str_free(VALUE str) } } -RUBY_FUNC_EXPORTED size_t +size_t rb_str_memsize(VALUE str) { if (FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) { diff --git a/variable.c b/variable.c index ab779f7420483f..564fd643fb1e4b 100644 --- a/variable.c +++ b/variable.c @@ -1166,7 +1166,7 @@ rb_free_generic_ivar(VALUE obj) } } -RUBY_FUNC_EXPORTED size_t +size_t rb_generic_ivar_memsize(VALUE obj) { struct gen_ivtbl *ivtbl; @@ -2546,7 +2546,7 @@ get_autoload_data(VALUE autoload_const_value, struct autoload_const **autoload_c return autoload_data; } -RUBY_FUNC_EXPORTED void +void rb_autoload(VALUE module, ID name, const char *feature) { if (!feature || !*feature) { From 4bb432722832b6451a289d906b08db322de6bad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20K=C3=BCthe?= Date: Mon, 12 Feb 2024 16:41:14 +0000 Subject: [PATCH 027/147] Fixes [Bug #20258] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Küthe --- ext/socket/mkconstants.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index ba7a55b4266b61..f8def9f990352a 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -762,6 +762,7 @@ def def_intern(func_name, pat, prefix_optional=nil) IPV6_PATHMTU nil Retrieve current path MTU IPV6_PKTINFO nil Receive packet information with datagram IPV6_RECVDSTOPTS nil Receive all IP6 options for response +IPV6_RECVERR nil Enable extended reliable error message passing IPV6_RECVHOPLIMIT nil Receive hop limit with datagram IPV6_RECVHOPOPTS nil Receive hop-by-hop options IPV6_RECVPKTINFO nil Receive destination IP address and incoming interface From 8b2c421a1741efc6f1aec6d9b7f0cd69bac097f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20K=C3=BCthe?= Date: Mon, 12 Feb 2024 18:09:18 +0000 Subject: [PATCH 028/147] Add option for mtu discovery flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marek Küthe --- ext/socket/mkconstants.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index f8def9f990352a..9150c3ff677903 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -748,6 +748,7 @@ def def_intern(func_name, pat, prefix_optional=nil) IPV6_JOIN_GROUP nil Join a group membership IPV6_LEAVE_GROUP nil Leave a group membership +IPV6_MTU_DISCOVER nil Path MTU discovery IPV6_MULTICAST_HOPS nil IP6 multicast hops IPV6_MULTICAST_IF nil IP6 multicast interface IPV6_MULTICAST_LOOP nil IP6 multicast loopback From 32f8ed7afd3234bc3c81936e5633cbf454723c49 Mon Sep 17 00:00:00 2001 From: Mike Shaver Date: Fri, 23 Feb 2024 11:18:22 -0500 Subject: [PATCH 029/147] Typo fix. --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index afd7969ae1a93b..8bfc6ed6d1ffc7 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9829,7 +9829,7 @@ parser_lex(pm_parser_t *parser) { ) { // Since we know we're about to add an __END__ comment, we know we - // need at add all of the newlines to get the correct column + // need to add all of the newlines to get the correct column // information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { From 6ad52e336d1733a0740186b7ee4df60c6e79030a Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 7 Jan 2023 04:23:10 +0900 Subject: [PATCH 030/147] [ruby/ipaddr] String#split seems to be faster than capturing digits with Regexp https://github.com/ruby/ipaddr/commit/e0feb0708b --- lib/ipaddr.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb index 1e4fd711cac5b1..35e2848939de00 100644 --- a/lib/ipaddr.rb +++ b/lib/ipaddr.rb @@ -52,7 +52,7 @@ class IPAddr # Regexp _internally_ used for parsing IPv4 address. RE_IPV4ADDRLIKE = %r{ \A - (\d+) \. (\d+) \. (\d+) \. (\d+) + \d+ \. \d+ \. \d+ \. \d+ \z }x @@ -669,8 +669,8 @@ def in_addr(addr) when Array octets = addr else - m = RE_IPV4ADDRLIKE.match(addr) or return nil - octets = m.captures + RE_IPV4ADDRLIKE.match?(addr) or return nil + octets = addr.split('.') end octets.inject(0) { |i, s| (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}" From 73dd3ce03e3a0a58a157607385418d7a3724752c Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 7 Jan 2023 04:10:12 +0900 Subject: [PATCH 031/147] [ruby/ipaddr] Prefer String#start_with? over Regexp.match https://github.com/ruby/ipaddr/commit/054fe12ec4 --- lib/ipaddr.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb index 35e2848939de00..a6734455321f64 100644 --- a/lib/ipaddr.rb +++ b/lib/ipaddr.rb @@ -674,7 +674,7 @@ def in_addr(addr) end octets.inject(0) { |i, s| (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}" - s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}" + (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}" i << 8 | n } end From d1ce989829927a4215952983babadfd1df1b505f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 10:36:59 -0500 Subject: [PATCH 032/147] [ruby/prism] Duplicated hash keys https://github.com/ruby/prism/commit/3e10c46c14 --- prism/diagnostic.c | 1 + prism/diagnostic.h | 1 + prism/node.h | 18 +++ prism/prism.c | 73 ++++++++-- prism/prism.h | 1 + prism/static_literals.c | 215 +++++++++++++++++++++++++++++ prism/static_literals.h | 109 +++++++++++++++ prism/templates/src/node.c.erb | 49 +++++-- prism/util/pm_integer.c | 23 +++ prism/util/pm_integer.h | 11 ++ test/prism/newline_test.rb | 2 +- test/prism/static_literals_test.rb | 68 +++++++++ 12 files changed, 545 insertions(+), 26 deletions(-) create mode 100644 prism/static_literals.c create mode 100644 prism/static_literals.h create mode 100644 test/prism/static_literals_test.rb diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 2040387d807be0..1003ecd3393dec 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -306,6 +306,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_PREFIX_STAR] = { "ambiguous `*` has been interpreted as an argument prefix", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_DUPLICATED_HASH_KEY] = { "key %.*s is duplicated and overwritten on line %" PRIi32, PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE } diff --git a/prism/diagnostic.h b/prism/diagnostic.h index 7419c0e791ae52..85f15db65c5737 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -306,6 +306,7 @@ typedef enum { PM_WARN_AMBIGUOUS_SLASH, PM_WARN_EQUAL_IN_CONDITIONAL, PM_WARN_END_IN_METHOD, + PM_WARN_DUPLICATED_HASH_KEY, PM_WARN_FLOAT_OUT_OF_RANGE, // This is the number of diagnostic codes. diff --git a/prism/node.h b/prism/node.h index 8d1b6a599a3344..9c37c9decce569 100644 --- a/prism/node.h +++ b/prism/node.h @@ -10,6 +10,17 @@ #include "prism/parser.h" #include "prism/util/pm_buffer.h" +/** + * Attempts to grow the node list to the next size. If there is already + * capacity in the list, this function does nothing. Otherwise it reallocates + * the list to be twice as large as it was before. If the reallocation fails, + * this function returns false, otherwise it returns true. + * + * @param list The list to grow. + * @return True if the list was successfully grown, false otherwise. + */ +bool pm_node_list_grow(pm_node_list_t *list); + /** * Append a new node onto the end of the node list. * @@ -18,6 +29,13 @@ */ void pm_node_list_append(pm_node_list_t *list, pm_node_t *node); +/** + * Free the internal memory associated with the given node list. + * + * @param list The list to free. + */ +void pm_node_list_free(pm_node_list_t *list); + /** * Deallocate a node and all of its children. * diff --git a/prism/prism.c b/prism/prism.c index 8bfc6ed6d1ffc7..fe1ba8d971c482 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11676,11 +11676,32 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { return statements; } +/** + * Add a node to a set of static literals that holds a set of hash keys. If the + * node is a duplicate, then add an appropriate warning. + */ +static void +pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { + const pm_node_t *duplicated = pm_static_literals_add(parser, literals, node); + + if (duplicated != NULL) { + pm_diagnostic_list_append_format( + &parser->warning_list, + duplicated->location.start, + duplicated->location.end, + PM_WARN_DUPLICATED_HASH_KEY, + (int) (duplicated->location.end - duplicated->location.start), + duplicated->location.start, + pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line + ); + } +} + /** * Parse all of the elements of a hash. returns true if a double splat was found. */ static bool -parse_assocs(pm_parser_t *parser, pm_node_t *node) { +parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { assert(PM_NODE_TYPE_P(node, PM_HASH_NODE) || PM_NODE_TYPE_P(node, PM_KEYWORD_HASH_NODE)); bool contains_keyword_splat = false; @@ -11709,6 +11730,8 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { parser_lex(parser); pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &label); + pm_hash_key_static_literals_add(parser, literals, key); + pm_token_t operator = not_provided(parser); pm_node_t *value = NULL; @@ -11738,8 +11761,16 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { } default: { pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_KEY); - pm_token_t operator; + // Hash keys that are strings are automatically frozen. We will + // mark that here. + if (PM_NODE_TYPE_P(key, PM_STRING_NODE)) { + pm_node_flag_set(key, PM_STRING_FLAGS_FROZEN | PM_NODE_FLAG_STATIC_LITERAL); + } + + pm_hash_key_static_literals_add(parser, literals, key); + + pm_token_t operator; if (pm_symbol_node_label_p(key)) { operator = not_provided(parser); } else { @@ -11773,6 +11804,7 @@ parse_assocs(pm_parser_t *parser, pm_node_t *node) { // Otherwise by default we will exit out of this loop. break; } + return contains_keyword_splat; } @@ -11830,12 +11862,17 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser); argument = (pm_node_t *) hash; - bool contains_keyword_splat = parse_assocs(parser, (pm_node_t *) hash); - parsed_bare_hash = true; + pm_static_literals_t literals = { 0 }; + bool contains_keyword_splat = parse_assocs(parser, &literals, (pm_node_t *) hash); + parse_arguments_append(parser, arguments, argument); if (contains_keyword_splat) { pm_node_flag_set((pm_node_t *)arguments->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT); } + + pm_static_literals_free(&literals); + parsed_bare_hash = true; + break; } case PM_TOKEN_UAMPERSAND: { @@ -11925,10 +11962,14 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for pm_keyword_hash_node_t *bare_hash = pm_keyword_hash_node_create(parser); + // Create the set of static literals for this hash. + pm_static_literals_t literals = { 0 }; + pm_hash_key_static_literals_add(parser, &literals, argument); + // Finish parsing the one we are part way through pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE); - argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value); + pm_keyword_hash_node_elements_append(bare_hash, argument); argument = (pm_node_t *) bare_hash; @@ -11937,9 +11978,10 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for token_begins_expression_p(parser->current.type) || match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL) )) { - contains_keyword_splat = parse_assocs(parser, (pm_node_t *) bare_hash); + contains_keyword_splat = parse_assocs(parser, &literals, (pm_node_t *) bare_hash); } + pm_static_literals_free(&literals); parsed_bare_hash = true; } else if (accept1(parser, PM_TOKEN_KEYWORD_IN)) { // TODO: Could we solve this with binding powers instead? @@ -14661,13 +14703,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_err_current(parser, PM_ERR_EXPRESSION_BARE_HASH); } - pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser); - element = (pm_node_t *)hash; + element = (pm_node_t *) pm_keyword_hash_node_create(parser); + pm_static_literals_t literals = { 0 }; if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) { - parse_assocs(parser, (pm_node_t *) hash); + parse_assocs(parser, &literals, element); } + pm_static_literals_free(&literals); parsed_bare_hash = true; } else { element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION); @@ -14678,6 +14721,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser); + pm_static_literals_t literals = { 0 }; + pm_hash_key_static_literals_add(parser, &literals, element); pm_token_t operator; if (parser->previous.type == PM_TOKEN_EQUAL_GREATER) { @@ -14690,11 +14735,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, element, &operator, value); pm_keyword_hash_node_elements_append(hash, assoc); - element = (pm_node_t *)hash; + element = (pm_node_t *) hash; if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) { - parse_assocs(parser, (pm_node_t *) hash); + parse_assocs(parser, &literals, element); } + pm_static_literals_free(&literals); parsed_bare_hash = true; } } @@ -14840,10 +14886,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b case PM_TOKEN_BRACE_LEFT: { pm_accepts_block_stack_push(parser, true); parser_lex(parser); + pm_hash_node_t *node = pm_hash_node_create(parser, &parser->previous); + pm_static_literals_t literals = { 0 }; if (!match2(parser, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_EOF)) { - parse_assocs(parser, (pm_node_t *) node); + parse_assocs(parser, &literals, (pm_node_t *) node); accept1(parser, PM_TOKEN_NEWLINE); } @@ -14851,6 +14899,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM); pm_hash_node_closing_loc_set(node, &parser->previous); + pm_static_literals_free(&literals); return (pm_node_t *) node; } case PM_TOKEN_CHARACTER_LITERAL: { diff --git a/prism/prism.h b/prism/prism.h index e24dbf5cad06e8..7d9b96fa829e99 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -21,6 +21,7 @@ #include "prism/parser.h" #include "prism/prettyprint.h" #include "prism/regexp.h" +#include "prism/static_literals.h" #include "prism/version.h" #include diff --git a/prism/static_literals.c b/prism/static_literals.c new file mode 100644 index 00000000000000..0fab4e98a3c108 --- /dev/null +++ b/prism/static_literals.c @@ -0,0 +1,215 @@ +#include "prism/static_literals.h" + +/** + * Insert a node into the given sorted list. This will return false if the node + * was not already in the list, and true if it was. + */ +static pm_node_t * +pm_node_list_insert(const pm_parser_t *parser, pm_node_list_t *list, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { + // TODO: This would be much more efficient with a binary search. + size_t index = 0; + while (index < list->size) { + int result = compare(parser, list->nodes[index], node); + + // If we find a match, then replace the node and return the old one. + if (result == 0) { + pm_node_t *result = list->nodes[index]; + list->nodes[index] = node; + return result; + } + + if (result > 0) break; + index++; + } + + pm_node_list_grow(list); + memmove(&list->nodes[index + 1], &list->nodes[index], (list->size - index) * sizeof(pm_node_t *)); + + list->nodes[index] = node; + list->size++; + + return NULL; +} + +/** + * Compare two values that can be compared with a simple numeric comparison. + */ +#define PM_NUMERIC_COMPARISON(left, right) ((left < right) ? -1 : (left > right) ? 1 : 0) + +/** + * Return the integer value of the given node as an int64_t. + */ +static int64_t +pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_INTEGER_NODE: { + const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value; + if (integer->length > 0) return integer->negative ? INT64_MIN : INT64_MAX; + + int64_t value = (int64_t) integer->head.value; + return integer->negative ? -value : value; + } + case PM_SOURCE_LINE_NODE: + return (int64_t) pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line; + default: + assert(false && "unreachable"); + return 0; + } +} + +/** + * A comparison function for comparing two IntegerNode or SourceLineNode + * instances. + */ +static int +pm_compare_integer_nodes(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) { + if (PM_NODE_TYPE_P(left, PM_SOURCE_LINE_NODE) || PM_NODE_TYPE_P(right, PM_SOURCE_LINE_NODE)) { + int64_t left_value = pm_int64_value(parser, left); + int64_t right_value = pm_int64_value(parser, right); + return PM_NUMERIC_COMPARISON(left_value, right_value); + } + + const pm_integer_t *left_integer = &((const pm_integer_node_t *) left)->value; + const pm_integer_t *right_integer = &((const pm_integer_node_t *) right)->value; + return pm_integer_compare(left_integer, right_integer); +} + +/** + * A comparison function for comparing two FloatNode instances. + */ +static int +pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) { + const double left_value = ((const pm_float_node_t *) left)->value; + const double right_value = ((const pm_float_node_t *) right)->value; + return PM_NUMERIC_COMPARISON(left_value, right_value); +} + +/** + * A comparison function for comparing two nodes that have attached numbers. + */ +static int +pm_compare_number_nodes(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) { + if (PM_NODE_TYPE(left) != PM_NODE_TYPE(right)) { + return PM_NUMERIC_COMPARISON(PM_NODE_TYPE(left), PM_NODE_TYPE(right)); + } + + switch (PM_NODE_TYPE(left)) { + case PM_IMAGINARY_NODE: + return pm_compare_number_nodes(parser, ((const pm_imaginary_node_t *) left)->numeric, ((const pm_imaginary_node_t *) right)->numeric); + case PM_RATIONAL_NODE: + return pm_compare_number_nodes(parser, ((const pm_rational_node_t *) left)->numeric, ((const pm_rational_node_t *) right)->numeric); + case PM_INTEGER_NODE: + return pm_compare_integer_nodes(parser, left, right); + case PM_FLOAT_NODE: + return pm_compare_float_nodes(parser, left, right); + default: + assert(false && "unreachable"); + return 0; + } +} + +/** + * Return a pointer to the string value of the given node. + */ +static const pm_string_t * +pm_string_value(const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_STRING_NODE: + return &((const pm_string_node_t *) node)->unescaped; + case PM_SOURCE_FILE_NODE: + return &((const pm_source_file_node_t *) node)->filepath; + case PM_SYMBOL_NODE: + return &((const pm_symbol_node_t *) node)->unescaped; + default: + assert(false && "unreachable"); + return NULL; + } +} + +/** + * A comparison function for comparing two nodes that have attached strings. + */ +static int +pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) { + const pm_string_t *left_string = pm_string_value(left); + const pm_string_t *right_string = pm_string_value(right); + return pm_string_compare(left_string, right_string); +} + +/** + * A comparison function for comparing two RegularExpressionNode instances. + */ +static int +pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right) { + const pm_regular_expression_node_t *left_regexp = (const pm_regular_expression_node_t *) left; + const pm_regular_expression_node_t *right_regexp = (const pm_regular_expression_node_t *) right; + + int result = pm_string_compare(&left_regexp->unescaped, &right_regexp->unescaped); + if (result != 0) return result; + + return PM_NUMERIC_COMPARISON(left_regexp->base.flags, right_regexp->base.flags); +} + +#undef PM_NUMERIC_COMPARISON + +/** + * Add a node to the set of static literals. + */ +pm_node_t * +pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { + if (!PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) return NULL; + + switch (PM_NODE_TYPE(node)) { + case PM_INTEGER_NODE: + case PM_SOURCE_LINE_NODE: + return pm_node_list_insert(parser, &literals->integer_nodes, node, pm_compare_integer_nodes); + case PM_FLOAT_NODE: + return pm_node_list_insert(parser, &literals->float_nodes, node, pm_compare_float_nodes); + case PM_RATIONAL_NODE: + case PM_IMAGINARY_NODE: + return pm_node_list_insert(parser, &literals->rational_nodes, node, pm_compare_number_nodes); + case PM_STRING_NODE: + case PM_SOURCE_FILE_NODE: + return pm_node_list_insert(parser, &literals->string_nodes, node, pm_compare_string_nodes); + case PM_REGULAR_EXPRESSION_NODE: + return pm_node_list_insert(parser, &literals->regexp_nodes, node, pm_compare_regular_expression_nodes); + case PM_SYMBOL_NODE: + return pm_node_list_insert(parser, &literals->symbol_nodes, node, pm_compare_string_nodes); + case PM_TRUE_NODE: { + pm_node_t *duplicated = literals->true_node; + literals->true_node = node; + return duplicated; + } + case PM_FALSE_NODE: { + pm_node_t *duplicated = literals->false_node; + literals->false_node = node; + return duplicated; + } + case PM_NIL_NODE: { + pm_node_t *duplicated = literals->nil_node; + literals->nil_node = node; + return duplicated; + } + case PM_SOURCE_ENCODING_NODE: { + pm_node_t *duplicated = literals->source_encoding_node; + literals->source_encoding_node = node; + return duplicated; + } + default: + return NULL; + } +} + +/** + * Free the internal memory associated with the given static literals set. + */ +void +pm_static_literals_free(pm_static_literals_t *literals) { + pm_node_list_free(&literals->integer_nodes); + pm_node_list_free(&literals->float_nodes); + pm_node_list_free(&literals->rational_nodes); + pm_node_list_free(&literals->imaginary_nodes); + pm_node_list_free(&literals->string_nodes); + pm_node_list_free(&literals->regexp_nodes); + pm_node_list_free(&literals->symbol_nodes); +} diff --git a/prism/static_literals.h b/prism/static_literals.h new file mode 100644 index 00000000000000..837d355985c6a6 --- /dev/null +++ b/prism/static_literals.h @@ -0,0 +1,109 @@ +/** + * @file static_literals.h + * + * A set of static literal nodes that can be checked for duplicates. + */ +#ifndef PRISM_STATIC_LITERALS_H +#define PRISM_STATIC_LITERALS_H + +#include "prism/defines.h" +#include "prism/ast.h" +#include "prism/node.h" +#include "prism/parser.h" + +#include +#include + +/** + * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes + * to alert the user of potential issues. To do this, we keep a set of the nodes + * that have been seen so far, and compare whenever we find a new node. + * + * We bucket the nodes based on their type to minimize the number of comparisons + * that need to be performed. + */ +typedef struct { + /** + * This is the set of IntegerNode and SourceLineNode instances. We store + * them in a sorted list so that we can binary search through them to find + * duplicates. + */ + pm_node_list_t integer_nodes; + + /** + * This is the set of FloatNode instances. We store them in a sorted list so + * that we can binary search through them to find duplicates. + */ + pm_node_list_t float_nodes; + + /** + * This is the set of RationalNode instances. We store them in a flat list + * that must be searched linearly. + */ + pm_node_list_t rational_nodes; + + /** + * This is the set of ImaginaryNode instances. We store them in a flat list + * that must be searched linearly. + */ + pm_node_list_t imaginary_nodes; + + /** + * This is the set of StringNode and SourceFileNode instances. We store them + * in a sorted list so that we can binary search through them to find + * duplicates. + */ + pm_node_list_t string_nodes; + + /** + * This is the set of RegularExpressionNode instances. We store them in a + * sorted list so that we can binary search through them to find duplicates. + */ + pm_node_list_t regexp_nodes; + + /** + * This is the set of SymbolNode instances. We store them in a sorted list + * so that we can binary search through them to find duplicates. + */ + pm_node_list_t symbol_nodes; + + /** + * A pointer to the last TrueNode instance that was inserted, or NULL. + */ + pm_node_t *true_node; + + /** + * A pointer to the last FalseNode instance that was inserted, or NULL. + */ + pm_node_t *false_node; + + /** + * A pointer to the last NilNode instance that was inserted, or NULL. + */ + pm_node_t *nil_node; + + /** + * A pointer to the last SourceEncodingNode instance that was inserted, or + * NULL. + */ + pm_node_t *source_encoding_node; +} pm_static_literals_t; + +/** + * Add a node to the set of static literals. + * + * @param parser The parser that created the node. + * @param literals The set of static literals to add the node to. + * @param node The node to add to the set. + * @return A pointer to the node that is being overwritten, if there is one. + */ +pm_node_t * pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node); + +/** + * Free the internal memory associated with the given static literals set. + * + * @param literals The set of static literals to free. + */ +void pm_static_literals_free(pm_static_literals_t *literals); + +#endif diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index 89c73451e8e457..554645c3e78629 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -17,32 +17,55 @@ pm_node_list_memsize(pm_node_list_t *node_list, pm_memsize_t *memsize) { } /** - * Append a new node onto the end of the node list. + * Attempts to grow the node list to the next size. If there is already + * capacity in the list, this function does nothing. Otherwise it reallocates + * the list to be twice as large as it was before. If the reallocation fails, + * this function returns false, otherwise it returns true. */ -void -pm_node_list_append(pm_node_list_t *list, pm_node_t *node) { +bool +pm_node_list_grow(pm_node_list_t *list) { if (list->size == list->capacity) { list->capacity = list->capacity == 0 ? 4 : list->capacity * 2; list->nodes = (pm_node_t **) realloc(list->nodes, sizeof(pm_node_t *) * list->capacity); + return list->nodes != NULL; + } + return true; +} + +/** + * Append a new node onto the end of the node list. + */ +void +pm_node_list_append(pm_node_list_t *list, pm_node_t *node) { + if (pm_node_list_grow(list)) { + list->nodes[list->size++] = node; + } +} + +/** + * Free the internal memory associated with the given node list. + */ +void +pm_node_list_free(pm_node_list_t *list) { + if (list->capacity > 0) { + free(list->nodes); + *list = (pm_node_list_t) { 0 }; } - list->nodes[list->size++] = node; } PRISM_EXPORTED_FUNCTION void pm_node_destroy(pm_parser_t *parser, pm_node_t *node); /** - * Deallocate the inner memory of a list of nodes. The parser argument is not - * used, but is here for the future possibility of pre-allocating memory pools. + * Destroy the nodes that are contained within the given node list. */ static void -pm_node_list_free(pm_parser_t *parser, pm_node_list_t *list) { - if (list->capacity > 0) { - for (size_t index = 0; index < list->size; index++) { - pm_node_destroy(parser, list->nodes[index]); - } - free(list->nodes); +pm_node_list_destroy(pm_parser_t *parser, pm_node_list_t *list) { + for (size_t index = 0; index < list->size; index++) { + pm_node_destroy(parser, list->nodes[index]); } + + pm_node_list_free(list); } /** @@ -71,7 +94,7 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) { <%- when Prism::StringField -%> pm_string_free(&cast-><%= field.name %>); <%- when Prism::NodeListField -%> - pm_node_list_free(parser, &cast-><%= field.name %>); + pm_node_list_destroy(parser, &cast-><%= field.name %>); <%- when Prism::ConstantListField -%> pm_constant_id_list_free(&cast-><%= field.name %>); <%- when Prism::IntegerField -%> diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index f08078356a531a..720dd608727acd 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -152,6 +152,29 @@ pm_integer_memsize(const pm_integer_t *integer) { return sizeof(pm_integer_t) + integer->length * sizeof(pm_integer_word_t); } +/** + * Compare two integers. This function returns -1 if the left integer is less + * than the right integer, 0 if they are equal, and 1 if the left integer is + * greater than the right integer. + */ +int +pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { + if (left->length < right->length) return -1; + if (left->length > right->length) return 1; + + for ( + const pm_integer_word_t *left_word = &left->head, *right_word = &right->head; + left_word != NULL && right_word != NULL; + left_word = left_word->next, right_word = right_word->next + ) { + if (left_word->value < right_word->value) return -1; + if (left_word->value > right_word->value) return 1; + } + + return 0; + +} + /** * Recursively destroy the linked list of an integer. */ diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h index 5525adabb03bb8..a80db633bbebd1 100644 --- a/prism/util/pm_integer.h +++ b/prism/util/pm_integer.h @@ -93,6 +93,17 @@ PRISM_EXPORTED_FUNCTION void pm_integer_parse(pm_integer_t *integer, pm_integer_ */ size_t pm_integer_memsize(const pm_integer_t *integer); +/** + * Compare two integers. This function returns -1 if the left integer is less + * than the right integer, 0 if they are equal, and 1 if the left integer is + * greater than the right integer. + * + * @param left The left integer to compare. + * @param right The right integer to compare. + * @return The result of the comparison. + */ +int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); + /** * Free the internal memory of an integer. This memory will only be allocated if * the integer exceeds the size of a single node in the linked list. diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index eea69ec5e12f3d..e9975b346e8e31 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -7,7 +7,7 @@ module Prism class NewlineTest < TestCase base = File.expand_path("../", __FILE__) - filepaths = Dir["*.rb", base: base] - %w[encoding_test.rb errors_test.rb parser_test.rb unescape_test.rb] + filepaths = Dir["*.rb", base: base] - %w[encoding_test.rb errors_test.rb parser_test.rb static_literals_test.rb unescape_test.rb] filepaths.each do |relative| define_method("test_newline_flags_#{relative}") do diff --git a/test/prism/static_literals_test.rb b/test/prism/static_literals_test.rb new file mode 100644 index 00000000000000..a35bb1cd49c43e --- /dev/null +++ b/test/prism/static_literals_test.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +module Prism + class StaticLiteralsTest < TestCase + def test_static_literals + assert_warning("1") + assert_warning("0xA", "10") + assert_warning("0o10", "8") + assert_warning("0b10", "2") + assert_warning("1_000") + assert_warning((2**32).to_s(10), "0x#{(2**32).to_s(16)}") + assert_warning((2**64).to_s(10), "0x#{(2**64).to_s(16)}") + + assert_warning("__LINE__", "2") + assert_warning("3", "__LINE__") + + assert_warning("1.0") + assert_warning("1e2", "100.0") + + assert_warning("1r") + assert_warning("1.0r") + + assert_warning("1i") + assert_warning("1.0i") + + assert_warning("1ri") + assert_warning("1.0ri") + + assert_warning("\"#{__FILE__}\"") + assert_warning("\"foo\"") + assert_warning("\"#{__FILE__}\"", "__FILE__") + + assert_warning("/foo/") + refute_warning("/foo/", "/foo/i") + + assert_warning(":foo") + assert_warning("%s[foo]") + + assert_warning("true") + assert_warning("false") + assert_warning("nil") + assert_warning("__ENCODING__") + end + + private + + def parse_warning(left, right) + source = <<~RUBY + { + #{left} => 1, + #{right} => 2 + } + RUBY + + Prism.parse(source, filepath: __FILE__).warnings.first + end + + def assert_warning(left, right = left) + assert_match %r{key #{Regexp.escape(left)} .+ line 3}, parse_warning(left, right)&.message + end + + def refute_warning(left, right) + assert_nil parse_warning(left, right) + end + end +end From a38cc177d29e13cf8116f7c08b408717a4edced1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 11:05:32 -0500 Subject: [PATCH 033/147] [ruby/prism] Duplicated when clauses https://github.com/ruby/prism/commit/865b0d5fbe --- lib/prism/prism.gemspec | 2 ++ prism/diagnostic.c | 1 + prism/diagnostic.h | 1 + prism/prism.c | 33 +++++++++++++++++-- prism/util/pm_integer.c | 1 - test/prism/snapshots/whitequark/case_expr.txt | 2 +- .../snapshots/whitequark/case_expr_else.txt | 2 +- .../prism/snapshots/whitequark/when_multi.txt | 4 +-- test/prism/snapshots/whitequark/when_then.txt | 2 +- test/prism/static_literals_test.rb | 23 ++++++++++--- 10 files changed, 58 insertions(+), 13 deletions(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 5017d671aec976..ac4bdddc21eb76 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -54,6 +54,7 @@ Gem::Specification.new do |spec| "include/prism/parser.h", "include/prism/prettyprint.h", "include/prism/regexp.h", + "include/prism/static_literals.h", "include/prism/util/pm_buffer.h", "include/prism/util/pm_char.h", "include/prism/util/pm_constant_pool.h", @@ -104,6 +105,7 @@ Gem::Specification.new do |spec| "src/prettyprint.c", "src/regexp.c", "src/serialize.c", + "src/static_literals.c", "src/token_type.c", "src/util/pm_buffer.c", "src/util/pm_char.c", diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 1003ecd3393dec..3dd07826abbb85 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -307,6 +307,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_WARN_AMBIGUOUS_PREFIX_STAR] = { "ambiguous `*` has been interpreted as an argument prefix", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_DUPLICATED_HASH_KEY] = { "key %.*s is duplicated and overwritten on line %" PRIi32, PM_WARNING_LEVEL_DEFAULT }, + [PM_WARN_DUPLICATED_WHEN_CLAUSE] = { "duplicated 'when' clause with line %" PRIi32 " is ignored", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE } diff --git a/prism/diagnostic.h b/prism/diagnostic.h index 85f15db65c5737..36f2f89ce896e6 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -307,6 +307,7 @@ typedef enum { PM_WARN_EQUAL_IN_CONDITIONAL, PM_WARN_END_IN_METHOD, PM_WARN_DUPLICATED_HASH_KEY, + PM_WARN_DUPLICATED_WHEN_CLAUSE, PM_WARN_FLOAT_OUT_OF_RANGE, // This is the number of diagnostic codes. diff --git a/prism/prism.c b/prism/prism.c index fe1ba8d971c482..bf32cedc2c1753 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11697,6 +11697,23 @@ pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *liter } } +/** + * Add a node to a set of static literals that holds a set of hash keys. If the + * node is a duplicate, then add an appropriate warning. + */ +static void +pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) { + if (pm_static_literals_add(parser, literals, node) != NULL) { + pm_diagnostic_list_append_format( + &parser->warning_list, + node->location.start, + node->location.end, + PM_WARN_DUPLICATED_WHEN_CLAUSE, + pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line).line + ); + } +} + /** * Parse all of the elements of a hash. returns true if a double splat was found. */ @@ -15335,10 +15352,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_KEYWORD_WHEN)) { pm_case_node_t *case_node = pm_case_node_create(parser, &case_keyword, predicate, &end_keyword); + pm_static_literals_t literals = { 0 }; // At this point we've seen a when keyword, so we know this is a - // case-when node. We will continue to parse the when nodes until we hit - // the end of the list. + // case-when node. We will continue to parse the when nodes + // until we hit the end of the list. while (accept1(parser, PM_TOKEN_KEYWORD_WHEN)) { pm_token_t when_keyword = parser->previous; pm_when_node_t *when_node = pm_when_node_create(parser, &when_keyword); @@ -15356,7 +15374,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN); pm_when_node_conditions_append(when_node, condition); + // If we found a missing node, then this is a syntax + // error and we should stop looping. if (PM_NODE_TYPE_P(condition, PM_MISSING_NODE)) break; + + // If this is a string node, then we need to mark it + // as frozen because when clause strings are frozen. + if (PM_NODE_TYPE_P(condition, PM_STRING_NODE)) { + pm_node_flag_set(condition, PM_STRING_FLAGS_FROZEN | PM_NODE_FLAG_STATIC_LITERAL); + } + + pm_when_clause_static_literals_add(parser, &literals, condition); } } while (accept1(parser, PM_TOKEN_COMMA)); @@ -15382,6 +15410,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS); } + pm_static_literals_free(&literals); node = (pm_node_t *) case_node; } else { pm_case_match_node_t *case_node = pm_case_match_node_create(parser, &case_keyword, predicate, &end_keyword); diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index 720dd608727acd..ff683d3501793c 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -172,7 +172,6 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { } return 0; - } /** diff --git a/test/prism/snapshots/whitequark/case_expr.txt b/test/prism/snapshots/whitequark/case_expr.txt index 6b209d9e4e9e33..9b43fece5c92bd 100644 --- a/test/prism/snapshots/whitequark/case_expr.txt +++ b/test/prism/snapshots/whitequark/case_expr.txt @@ -20,7 +20,7 @@ │ ├── keyword_loc: (1,10)-(1,14) = "when" │ ├── conditions: (length: 1) │ │ └── @ StringNode (location: (1,15)-(1,20)) - │ │ ├── flags: ∅ + │ │ ├── flags: frozen │ │ ├── opening_loc: (1,15)-(1,16) = "'" │ │ ├── content_loc: (1,16)-(1,19) = "bar" │ │ ├── closing_loc: (1,19)-(1,20) = "'" diff --git a/test/prism/snapshots/whitequark/case_expr_else.txt b/test/prism/snapshots/whitequark/case_expr_else.txt index 5729140685beee..20501ab511cfa3 100644 --- a/test/prism/snapshots/whitequark/case_expr_else.txt +++ b/test/prism/snapshots/whitequark/case_expr_else.txt @@ -20,7 +20,7 @@ │ ├── keyword_loc: (1,10)-(1,14) = "when" │ ├── conditions: (length: 1) │ │ └── @ StringNode (location: (1,15)-(1,20)) - │ │ ├── flags: ∅ + │ │ ├── flags: frozen │ │ ├── opening_loc: (1,15)-(1,16) = "'" │ │ ├── content_loc: (1,16)-(1,19) = "bar" │ │ ├── closing_loc: (1,19)-(1,20) = "'" diff --git a/test/prism/snapshots/whitequark/when_multi.txt b/test/prism/snapshots/whitequark/when_multi.txt index 0fa7cd69ba7ea1..a92c167d06dd20 100644 --- a/test/prism/snapshots/whitequark/when_multi.txt +++ b/test/prism/snapshots/whitequark/when_multi.txt @@ -20,13 +20,13 @@ │ ├── keyword_loc: (1,10)-(1,14) = "when" │ ├── conditions: (length: 2) │ │ ├── @ StringNode (location: (1,15)-(1,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: frozen │ │ │ ├── opening_loc: (1,15)-(1,16) = "'" │ │ │ ├── content_loc: (1,16)-(1,19) = "bar" │ │ │ ├── closing_loc: (1,19)-(1,20) = "'" │ │ │ └── unescaped: "bar" │ │ └── @ StringNode (location: (1,22)-(1,27)) - │ │ ├── flags: ∅ + │ │ ├── flags: frozen │ │ ├── opening_loc: (1,22)-(1,23) = "'" │ │ ├── content_loc: (1,23)-(1,26) = "baz" │ │ ├── closing_loc: (1,26)-(1,27) = "'" diff --git a/test/prism/snapshots/whitequark/when_then.txt b/test/prism/snapshots/whitequark/when_then.txt index d6b438c39ec3c4..402d43b6767499 100644 --- a/test/prism/snapshots/whitequark/when_then.txt +++ b/test/prism/snapshots/whitequark/when_then.txt @@ -20,7 +20,7 @@ │ ├── keyword_loc: (1,10)-(1,14) = "when" │ ├── conditions: (length: 1) │ │ └── @ StringNode (location: (1,15)-(1,20)) - │ │ ├── flags: ∅ + │ │ ├── flags: frozen │ │ ├── opening_loc: (1,15)-(1,16) = "'" │ │ ├── content_loc: (1,16)-(1,19) = "bar" │ │ ├── closing_loc: (1,19)-(1,20) = "'" diff --git a/test/prism/static_literals_test.rb b/test/prism/static_literals_test.rb index a35bb1cd49c43e..b28f1f91875930 100644 --- a/test/prism/static_literals_test.rb +++ b/test/prism/static_literals_test.rb @@ -46,23 +46,36 @@ def test_static_literals private - def parse_warning(left, right) - source = <<~RUBY + def parse_warnings(left, right) + warnings = [] + + warnings << Prism.parse(<<~RUBY, filepath: __FILE__).warnings.first { #{left} => 1, #{right} => 2 } RUBY - Prism.parse(source, filepath: __FILE__).warnings.first + warnings << Prism.parse(<<~RUBY, filepath: __FILE__).warnings.first + case foo + when #{left} + when #{right} + end + RUBY + + warnings end def assert_warning(left, right = left) - assert_match %r{key #{Regexp.escape(left)} .+ line 3}, parse_warning(left, right)&.message + hash_keys, when_clauses = parse_warnings(left, right) + + assert_include hash_keys.message, left + assert_include hash_keys.message, "line 3" + assert_include when_clauses.message, "line 3" end def refute_warning(left, right) - assert_nil parse_warning(left, right) + assert_empty parse_warnings(left, right).compact end end end From b9202788f8a1098994082aee5bcb9f6d0cc73eb0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 11:44:19 -0500 Subject: [PATCH 034/147] [ruby/prism] Refactor pm_node_list_insert to use a binary search https://github.com/ruby/prism/commit/a060b21e1d --- prism/static_literals.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/prism/static_literals.c b/prism/static_literals.c index 0fab4e98a3c108..5fba5d790effc5 100644 --- a/prism/static_literals.c +++ b/prism/static_literals.c @@ -6,26 +6,32 @@ */ static pm_node_t * pm_node_list_insert(const pm_parser_t *parser, pm_node_list_t *list, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { - // TODO: This would be much more efficient with a binary search. - size_t index = 0; - while (index < list->size) { - int result = compare(parser, list->nodes[index], node); + size_t low = 0; + size_t high = list->size; - // If we find a match, then replace the node and return the old one. + while (low < high) { + size_t mid = (low + high) / 2; + int result = compare(parser, list->nodes[mid], node); + + // If we find a match, then replace the old node with the new one and + // return the old one. if (result == 0) { - pm_node_t *result = list->nodes[index]; - list->nodes[index] = node; + pm_node_t *result = list->nodes[mid]; + list->nodes[mid] = node; return result; } - if (result > 0) break; - index++; + if (result < 0) { + low = mid + 1; + } else { + high = mid; + } } pm_node_list_grow(list); - memmove(&list->nodes[index + 1], &list->nodes[index], (list->size - index) * sizeof(pm_node_t *)); + memmove(&list->nodes[low + 1], &list->nodes[low], (list->size - low) * sizeof(pm_node_t *)); - list->nodes[index] = node; + list->nodes[low] = node; list->size++; return NULL; From 02b531a813a6d68eea8b93aaf33fac57837ad90c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 12:39:11 -0500 Subject: [PATCH 035/147] [ruby/prism] Factor in sign to integer comparison https://github.com/ruby/prism/commit/377666a5df --- prism/util/pm_integer.c | 11 +++++++---- test/prism/static_literals_test.rb | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index ff683d3501793c..e39108a05b2728 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -159,16 +159,19 @@ pm_integer_memsize(const pm_integer_t *integer) { */ int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { - if (left->length < right->length) return -1; - if (left->length > right->length) return 1; + if (left->negative != right->negative) return left->negative ? -1 : 1; + int negative = left->negative ? -1 : 1; + + if (left->length < right->length) return -1 * negative; + if (left->length > right->length) return 1 * negative; for ( const pm_integer_word_t *left_word = &left->head, *right_word = &right->head; left_word != NULL && right_word != NULL; left_word = left_word->next, right_word = right_word->next ) { - if (left_word->value < right_word->value) return -1; - if (left_word->value > right_word->value) return 1; + if (left_word->value < right_word->value) return -1 * negative; + if (left_word->value > right_word->value) return 1 * negative; } return 0; diff --git a/test/prism/static_literals_test.rb b/test/prism/static_literals_test.rb index b28f1f91875930..6108e2ddbc5a04 100644 --- a/test/prism/static_literals_test.rb +++ b/test/prism/static_literals_test.rb @@ -13,6 +13,10 @@ def test_static_literals assert_warning((2**32).to_s(10), "0x#{(2**32).to_s(16)}") assert_warning((2**64).to_s(10), "0x#{(2**64).to_s(16)}") + refute_warning("1", "-1") + refute_warning((2**32).to_s(10), "-0x#{(2**32).to_s(16)}") + refute_warning((2**64).to_s(10), "-0x#{(2**64).to_s(16)}") + assert_warning("__LINE__", "2") assert_warning("3", "__LINE__") @@ -33,6 +37,7 @@ def test_static_literals assert_warning("\"#{__FILE__}\"", "__FILE__") assert_warning("/foo/") + refute_warning("/foo/", "/foo/i") assert_warning(":foo") From 9a09e27a73898221656f9bd67a2edf1dc0475d60 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 12:39:46 -0500 Subject: [PATCH 036/147] [PRISM] Use new static literal comparisons --- common.mk | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/common.mk b/common.mk index 60c2a9a12a85b8..610ff015a7f1fd 100644 --- a/common.mk +++ b/common.mk @@ -96,6 +96,7 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \ prism/prettyprint.$(OBJEXT) \ prism/regexp.$(OBJEXT) \ prism/serialize.$(OBJEXT) \ + prism/static_literals.$(OBJEXT) \ prism/token_type.$(OBJEXT) \ prism/util/pm_buffer.$(OBJEXT) \ prism/util/pm_char.$(OBJEXT) \ @@ -2242,6 +2243,7 @@ ast.$(OBJEXT): $(top_srcdir)/prism/parser.h ast.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h ast.$(OBJEXT): $(top_srcdir)/prism/prism.h ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h +ast.$(OBJEXT): $(top_srcdir)/prism/static_literals.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -2678,6 +2680,7 @@ builtin.$(OBJEXT): $(top_srcdir)/prism/parser.h builtin.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h builtin.$(OBJEXT): $(top_srcdir)/prism/prism.h builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h +builtin.$(OBJEXT): $(top_srcdir)/prism/static_literals.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -3311,6 +3314,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/parser.h compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h compile.$(OBJEXT): $(top_srcdir)/prism/prism.h compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h +compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -3774,6 +3778,7 @@ cont.$(OBJEXT): $(top_srcdir)/prism/parser.h cont.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h cont.$(OBJEXT): $(top_srcdir)/prism/prism.h cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h +cont.$(OBJEXT): $(top_srcdir)/prism/static_literals.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -6744,6 +6749,7 @@ eval.$(OBJEXT): $(top_srcdir)/prism/parser.h eval.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h eval.$(OBJEXT): $(top_srcdir)/prism/prism.h eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h +eval.$(OBJEXT): $(top_srcdir)/prism/static_literals.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -7224,6 +7230,7 @@ gc.$(OBJEXT): $(top_srcdir)/prism/parser.h gc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h gc.$(OBJEXT): $(top_srcdir)/prism/prism.h gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h +gc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -7480,6 +7487,7 @@ goruby.$(OBJEXT): $(top_srcdir)/prism/parser.h goruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h goruby.$(OBJEXT): $(top_srcdir)/prism/prism.h goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h +goruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -7723,6 +7731,7 @@ hash.$(OBJEXT): $(top_srcdir)/prism/parser.h hash.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h hash.$(OBJEXT): $(top_srcdir)/prism/prism.h hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h +hash.$(OBJEXT): $(top_srcdir)/prism/static_literals.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -8758,6 +8767,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h +iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -9014,6 +9024,7 @@ load.$(OBJEXT): $(top_srcdir)/prism/parser.h load.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h load.$(OBJEXT): $(top_srcdir)/prism/prism.h load.$(OBJEXT): $(top_srcdir)/prism/regexp.h +load.$(OBJEXT): $(top_srcdir)/prism/static_literals.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -10344,6 +10355,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/prism/parser.h miniinit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h miniinit.$(OBJEXT): $(top_srcdir)/prism/prism.h miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -11926,6 +11938,7 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12121,6 +12134,7 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12329,6 +12343,7 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12568,6 +12583,7 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.c prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12611,6 +12627,7 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12627,6 +12644,23 @@ prism/serialize.$(OBJEXT): {$(VPATH)}config.h prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.c +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_state_stack.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h @@ -12718,6 +12752,7 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/parser.h prism_init.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism_init.$(OBJEXT): $(top_srcdir)/prism/prism.h prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -12934,6 +12969,7 @@ proc.$(OBJEXT): $(top_srcdir)/prism/parser.h proc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h proc.$(OBJEXT): $(top_srcdir)/prism/prism.h proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h +proc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -15417,6 +15453,7 @@ rjit.$(OBJEXT): $(top_srcdir)/prism/parser.h rjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h rjit.$(OBJEXT): $(top_srcdir)/prism/prism.h rjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +rjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -15670,6 +15707,7 @@ rjit_c.$(OBJEXT): $(top_srcdir)/prism/parser.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/prism.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/regexp.h +rjit_c.$(OBJEXT): $(top_srcdir)/prism/static_literals.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -15949,6 +15987,7 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/parser.h ruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h ruby.$(OBJEXT): $(top_srcdir)/prism/prism.h ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h +ruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -18390,6 +18429,7 @@ thread.$(OBJEXT): $(top_srcdir)/prism/parser.h thread.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h thread.$(OBJEXT): $(top_srcdir)/prism/prism.h thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h +thread.$(OBJEXT): $(top_srcdir)/prism/static_literals.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -19651,6 +19691,7 @@ vm.$(OBJEXT): $(top_srcdir)/prism/parser.h vm.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h vm.$(OBJEXT): $(top_srcdir)/prism/prism.h vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm.$(OBJEXT): $(top_srcdir)/prism/static_literals.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -19909,6 +19950,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/parser.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prism.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -20139,6 +20181,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/prism/parser.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/prism.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/static_literals.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -20580,6 +20623,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/prism/parser.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/prism.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -21021,6 +21065,7 @@ yjit.$(OBJEXT): $(top_srcdir)/prism/parser.h yjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h yjit.$(OBJEXT): $(top_srcdir)/prism/prism.h yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +yjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h From 01f9b2ae4142f0c0d3d2dec9ea141572265d05b2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 16:30:59 -0500 Subject: [PATCH 037/147] Use rb_str_to_interned_str in parse.y This commit changes rb_fstring to rb_str_to_interned_str in parse.y. rb_fstring is private so it shouldn't be used by ripper. --- parse.y | 8 ++++---- ruby_parser.c | 2 +- rubyparser.h | 2 +- universal_parser.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/parse.y b/parse.y index 1631bdecc2bf36..36803394fdde8f 100644 --- a/parse.y +++ b/parse.y @@ -7637,7 +7637,7 @@ yycompile(struct parser_params *p, VALUE fname, int line) p->ruby_sourcefile = "(none)"; } else { - p->ruby_sourcefile_string = rb_fstring(fname); + p->ruby_sourcefile_string = rb_str_to_interned_str(fname); p->ruby_sourcefile = StringValueCStr(fname); } p->ruby_sourceline = line - 1; @@ -13485,7 +13485,7 @@ rb_parser_trace_lex_state(struct parser_params *p, enum lex_state_e from, VALUE rb_parser_lex_state_name(struct parser_params *p, enum lex_state_e state) { - return rb_fstring(append_lex_state_name(p, state, rb_str_new(0, 0))); + return rb_str_to_interned_str(append_lex_state_name(p, state, rb_str_new(0, 0))); } static void @@ -14026,13 +14026,13 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable, return value; case NODE_STR: - lit = rb_fstring(rb_node_str_string_val(value)); + lit = rb_str_to_interned_str(rb_node_str_string_val(value)); value = NEW_LIT(lit, loc); RB_OBJ_WRITE(p->ast, &RNODE_LIT(value)->nd_lit, lit); return value; case NODE_FILE: - lit = rb_fstring(rb_node_file_path_val(value)); + lit = rb_str_to_interned_str(rb_node_file_path_val(value)); value = NEW_LIT(lit, loc); RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(value)->nd_lit); return value; diff --git a/ruby_parser.c b/ruby_parser.c index c4b4ffc1a319f6..8e2371fd1d92dd 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -533,7 +533,7 @@ static const rb_parser_config_t rb_global_parser_config = { .str_resize = rb_str_resize, .str_new = rb_str_new, .str_new_cstr = rb_str_new_cstr, - .fstring = rb_fstring, + .str_to_interned_str = rb_str_to_interned_str, .is_ascii_string = is_ascii_string2, .enc_str_new = enc_str_new, .enc_str_buf_cat = enc_str_buf_cat, diff --git a/rubyparser.h b/rubyparser.h index ab8a39367d4a5e..34ee117f650974 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1272,7 +1272,7 @@ typedef struct rb_parser_config_struct { VALUE (*str_resize)(VALUE str, long len); VALUE (*str_new)(const char *ptr, long len); VALUE (*str_new_cstr)(const char *ptr); - VALUE (*fstring)(VALUE); + VALUE (*str_to_interned_str)(VALUE); int (*is_ascii_string)(VALUE str); VALUE (*enc_str_new)(const char *ptr, long len, rb_encoding *enc); VALUE (*enc_str_buf_cat)(VALUE str, const char *ptr, long len, rb_encoding *enc); diff --git a/universal_parser.c b/universal_parser.c index a3edbb92472ba6..2cd5c7407badc5 100644 --- a/universal_parser.c +++ b/universal_parser.c @@ -157,7 +157,7 @@ struct rb_imemo_tmpbuf_struct { #define rb_str_new p->config->str_new #undef rb_str_new_cstr #define rb_str_new_cstr p->config->str_new_cstr -#define rb_fstring p->config->fstring +#define rb_str_to_interned_str p->config->str_to_interned_str #define is_ascii_string p->config->is_ascii_string #define rb_enc_str_new p->config->enc_str_new #define rb_enc_str_buf_cat p->config->enc_str_buf_cat From 510404f2def62918849797e742642254700e3608 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 22 Feb 2024 16:14:11 -0500 Subject: [PATCH 038/147] Stop using rb_fstring publicly rb_fstring is a private API, so we should use rb_str_to_interned_str instead, which is a public API. --- ext/-test-/string/fstring.c | 6 ++---- spec/ruby/optional/capi/ext/string_spec.c | 4 +--- string.c | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c index 7ee14a8570f7d0..d3062224d88e81 100644 --- a/ext/-test-/string/fstring.c +++ b/ext/-test-/string/fstring.c @@ -2,12 +2,10 @@ #include "ruby/encoding.h" #include "internal/string.h" -VALUE rb_fstring(VALUE str); - VALUE bug_s_fstring(VALUE self, VALUE str) { - return rb_fstring(str); + return rb_str_to_interned_str(str); } VALUE @@ -15,7 +13,7 @@ bug_s_fstring_fake_str(VALUE self) { static const char literal[] = "abcdefghijklmnopqrstuvwxyz"; struct RString fake_str; - return rb_fstring(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0)); + return rb_str_to_interned_str(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0)); } VALUE diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index 2bd789fb72862a..c9c5277732ecbf 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -51,10 +51,8 @@ VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) { return INT2FIX(RSTRING_LEN(str)); } -VALUE rb_fstring(VALUE str); /* internal.h, used in ripper */ - VALUE string_spec_rb_str_fstring(VALUE self, VALUE str) { - return rb_fstring(str); + return rb_str_to_interned_str(str); } VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) { diff --git a/string.c b/string.c index 24dd29b32e2528..8ed058eead8954 100644 --- a/string.c +++ b/string.c @@ -398,7 +398,6 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist } } -RUBY_FUNC_EXPORTED VALUE rb_fstring(VALUE str) { From 50ace992c75724aac6765b944f9017e21901e276 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 12 Feb 2024 13:16:25 -0500 Subject: [PATCH 039/147] [Bug #20234] Fix segv when parsing begin statement in method definition In a method definition, the `begin` may not have an `nd_body`. When that happens we get a null expr back from `last_expr_node` which causes a segv for the following examples: ```ruby def (begin;end).foo; end def (begin;else;end).foo; end def (begin;ensure;else;end).foo; end ``` In addition, I've added tests for other cases that weren't causing a segv but appeared untested.` Fixes https://bugs.ruby-lang.org/issues/20234 --- parse.y | 2 +- test/ruby/test_parse.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 36803394fdde8f..bee79c9f6c51bf 100644 --- a/parse.y +++ b/parse.y @@ -1415,7 +1415,7 @@ last_expr_node(NODE *expr) if (nd_type_p(expr, NODE_BLOCK)) { expr = RNODE_BLOCK(RNODE_BLOCK(expr)->nd_end)->nd_head; } - else if (nd_type_p(expr, NODE_BEGIN)) { + else if (nd_type_p(expr, NODE_BEGIN) && RNODE_BEGIN(expr)->nd_body) { expr = RNODE_BEGIN(expr)->nd_body; } else { diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index e74406b84348cb..a8abccb1f937b3 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1109,6 +1109,16 @@ def test_unused_variable assert_warning('') {o.instance_eval("def marg2((a)); nil; end")} end + def test_parsing_begin_statement_inside_method_definition + assert_equal :bug_20234, eval("def (begin;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;rescue;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;ensure;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;rescue;else;end).bug_20234; end") + + assert_raise(SyntaxError) { eval("def (begin;else;end).bug_20234; end") } + assert_raise(SyntaxError) { eval("def (begin;ensure;else;end).bug_20234; end") } + end + def test_named_capture_conflict a = 1 assert_warning('') {eval("a = 1; /(?)/ =~ ''")} From 8a6740c70edf39cdf6230659d191240c43dc6d22 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 23 Feb 2024 11:08:09 -0800 Subject: [PATCH 040/147] YJIT: Lazily push a frame for specialized C funcs (#10080) * YJIT: Lazily push a frame for specialized C funcs Co-authored-by: Maxime Chevalier-Boisvert * Fix a comment on pc_to_cfunc * Rename rb_yjit_check_pc to rb_yjit_lazy_push_frame * Rename it to jit_prepare_lazy_frame_call * Fix a typo * Optimize String#getbyte as well * Optimize String#byteslice as well --------- Co-authored-by: Maxime Chevalier-Boisvert --- bootstraptest/test_yjit.rb | 51 +++++++++++++++++ common.mk | 2 + error.c | 3 + object.c | 2 + string.c | 2 +- vm_insnhelper.c | 18 ++++++ yjit.h | 2 + yjit.rb | 4 ++ yjit/src/codegen.rs | 109 ++++++++++++++++++++++++++++++++++--- yjit/src/cruby.rs | 2 + yjit/src/stats.rs | 5 ++ yjit/src/yjit.rs | 16 ++++++ 12 files changed, 206 insertions(+), 10 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 2e475cc186bca4..a2c98c01c939aa 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -2046,6 +2046,57 @@ def getbyte(s, i) [getbyte("a", 0), getbyte("a", 1), getbyte("a", -1), getbyte("a", -2), getbyte("a", "a")] } unless rjit_enabled? # Not yet working on RJIT +# Basic test for String#setbyte +assert_equal 'AoZ', %q{ + s = "foo" + s.setbyte(0, 65) + s.setbyte(-1, 90) + s +} + +# String#setbyte IndexError +assert_equal 'String#setbyte', %q{ + def ccall = "".setbyte(1, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# String#setbyte TypeError +assert_equal 'String#setbyte', %q{ + def ccall = "".setbyte(nil, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# String#setbyte FrozenError +assert_equal 'String#setbyte', %q{ + def ccall = "a".freeze.setbyte(0, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# non-leaf String#setbyte +assert_equal 'String#setbyte', %q{ + def to_int + @caller = caller + 0 + end + + def ccall = "a".setbyte(self, 98) + ccall + + @caller.first.split("'").last +} + # non-leaf String#byteslice assert_equal 'TypeError', %q{ def ccall = "".byteslice(nil, nil) diff --git a/common.mk b/common.mk index 610ff015a7f1fd..f9d16b4ea2de6c 100644 --- a/common.mk +++ b/common.mk @@ -6711,6 +6711,7 @@ error.$(OBJEXT): {$(VPATH)}util.h error.$(OBJEXT): {$(VPATH)}vm_core.h error.$(OBJEXT): {$(VPATH)}vm_opts.h error.$(OBJEXT): {$(VPATH)}warning.rbinc +error.$(OBJEXT): {$(VPATH)}yjit.h eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h eval.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -11425,6 +11426,7 @@ object.$(OBJEXT): {$(VPATH)}vm_core.h object.$(OBJEXT): {$(VPATH)}vm_debug.h object.$(OBJEXT): {$(VPATH)}vm_opts.h object.$(OBJEXT): {$(VPATH)}vm_sync.h +object.$(OBJEXT): {$(VPATH)}yjit.h pack.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h pack.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h pack.$(OBJEXT): $(CCAN_DIR)/list/list.h diff --git a/error.c b/error.c index 385da82f3865f0..ac579777bebc98 100644 --- a/error.c +++ b/error.c @@ -48,6 +48,7 @@ #include "ruby/util.h" #include "ruby_assert.h" #include "vm_core.h" +#include "yjit.h" #include "builtin.h" @@ -1409,6 +1410,7 @@ rb_exc_new_cstr(VALUE etype, const char *s) VALUE rb_exc_new_str(VALUE etype, VALUE str) { + rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); StringValue(str); return rb_class_new_instance(1, &str, etype); } @@ -3827,6 +3829,7 @@ inspect_frozen_obj(VALUE obj, VALUE mesg, int recur) void rb_error_frozen_object(VALUE frozen_obj) { + rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); VALUE debug_info; const ID created_info = id_debug_created_info; VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ", diff --git a/object.c b/object.c index 69602ac8d09035..7ec944cb7a13c3 100644 --- a/object.c +++ b/object.c @@ -42,6 +42,7 @@ #include "ruby/assert.h" #include "builtin.h" #include "shape.h" +#include "yjit.h" /* Flags of RObject * @@ -3238,6 +3239,7 @@ rb_to_integer_with_id_exception(VALUE val, const char *method, ID mid, int raise VALUE v; if (RB_INTEGER_TYPE_P(val)) return val; + rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); v = try_to_int(val, mid, raise); if (!raise && NIL_P(v)) return Qnil; if (!RB_INTEGER_TYPE_P(v)) { diff --git a/string.c b/string.c index 8ed058eead8954..d8b145db06a5fa 100644 --- a/string.c +++ b/string.c @@ -6173,7 +6173,7 @@ rb_str_getbyte(VALUE str, VALUE index) * * Related: String#getbyte. */ -static VALUE +VALUE rb_str_setbyte(VALUE str, VALUE index, VALUE value) { long pos = NUM2LONG(index); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index bee3d0a8c68490..6136cb146596e9 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3535,6 +3535,24 @@ vm_call_cfunc_with_frame_(rb_execution_context_t *ec, rb_control_frame_t *reg_cf return val; } +// Push a C method frame for a given cme. This is called when JIT code skipped +// pushing a frame but the C method reached a point where a frame is needed. +void +rb_vm_push_cfunc_frame(const rb_callable_method_entry_t *cme, int recv_idx) +{ + VM_ASSERT(cme->def->type == VM_METHOD_TYPE_CFUNC); + rb_execution_context_t *ec = GET_EC(); + VALUE *sp = ec->cfp->sp; + VALUE recv = *(sp - recv_idx - 1); + VALUE frame_type = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL; + VALUE block_handler = VM_BLOCK_HANDLER_NONE; +#if VM_CHECK_MODE > 0 + // Clean up the stack canary since we're about to satisfy the "leaf or lazy push" assumption + *(GET_EC()->cfp->sp) = Qfalse; +#endif + vm_push_frame(ec, NULL, frame_type, recv, block_handler, (VALUE)cme, 0, ec->cfp->sp, 0, 0); +} + // If true, cc->call needs to include `CALLER_SETUP_ARG` (i.e. can't be skipped in fastpath) bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci) diff --git a/yjit.h b/yjit.h index 5e71b2f276f3b5..46218a47d72d44 100644 --- a/yjit.h +++ b/yjit.h @@ -45,6 +45,7 @@ void rb_yjit_before_ractor_spawn(void); void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx); void rb_yjit_tracing_invalidate_all(void); void rb_yjit_show_usage(int help, int highlight, unsigned int width, int columns); +void rb_yjit_lazy_push_frame(const VALUE *pc); #else // !USE_YJIT @@ -66,6 +67,7 @@ static inline void rb_yjit_iseq_free(void *payload) {} static inline void rb_yjit_before_ractor_spawn(void) {} static inline void rb_yjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx) {} static inline void rb_yjit_tracing_invalidate_all(void) {} +static inline void rb_yjit_lazy_push_frame(const VALUE *pc) {} #endif // #if USE_YJIT diff --git a/yjit.rb b/yjit.rb index f2cd369faf0f64..50cb2483980fec 100644 --- a/yjit.rb +++ b/yjit.rb @@ -332,6 +332,10 @@ def _print_stats(out: $stderr) # :nodoc: out.puts "num_throw_break: " + format_number_pct(13, stats[:num_throw_break], stats[:num_throw]) out.puts "num_throw_retry: " + format_number_pct(13, stats[:num_throw_retry], stats[:num_throw]) out.puts "num_throw_return: " + format_number_pct(13, stats[:num_throw_return], stats[:num_throw]) + out.puts "num_lazy_frame_check: " + format_number(13, stats[:num_lazy_frame_check]) + out.puts "num_lazy_frame_push: " + format_number_pct(13, stats[:num_lazy_frame_push], stats[:num_lazy_frame_check]) + out.puts "lazy_frame_count: " + format_number(13, stats[:lazy_frame_count]) + out.puts "lazy_frame_failure: " + format_number(13, stats[:lazy_frame_failure]) out.puts "iseq_stack_too_large: " + format_number(13, stats[:iseq_stack_too_large]) out.puts "iseq_too_long: " + format_number(13, stats[:iseq_too_long]) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 333e8500743794..7148f4a4e60abb 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -411,6 +411,54 @@ fn gen_save_sp_with_offset(asm: &mut Assembler, offset: i8) { } } +/// Basically jit_prepare_non_leaf_call(), but this registers the current PC +/// to lazily push a C method frame when it's necessary. +fn jit_prepare_lazy_frame_call( + jit: &mut JITState, + asm: &mut Assembler, + cme: *const rb_callable_method_entry_t, + recv_opnd: YARVOpnd, +) -> bool { + // We can use this only when the receiver is on stack. + let recv_idx = match recv_opnd { + StackOpnd(recv_idx) => recv_idx, + _ => unreachable!("recv_opnd must be on stack, but got: {:?}", recv_opnd), + }; + + // Get the next PC. jit_save_pc() saves that PC. + let pc: *mut VALUE = unsafe { + let cur_insn_len = insn_len(jit.get_opcode()) as isize; + jit.get_pc().offset(cur_insn_len) + }; + + let pc_to_cfunc = CodegenGlobals::get_pc_to_cfunc(); + match pc_to_cfunc.get(&pc) { + Some(&(other_cme, _)) if other_cme != cme => { + // Bail out if it's not the only cme on this callsite. + incr_counter!(lazy_frame_failure); + return false; + } + _ => { + // Let rb_yjit_lazy_push_frame() lazily push a C frame on this PC. + incr_counter!(lazy_frame_count); + pc_to_cfunc.insert(pc, (cme, recv_idx)); + } + } + + // Save the PC to trigger a lazy frame push, and save the SP to get the receiver. + // The C func may call a method that doesn't raise, so prepare for invalidation too. + jit_prepare_non_leaf_call(jit, asm); + + // Make sure we're ready for calling rb_vm_push_cfunc_frame(). + let cfunc_argc = unsafe { get_mct_argc(get_cme_def_body_cfunc(cme)) }; + if cfunc_argc != -1 { + assert_eq!(recv_idx as i32, cfunc_argc); // verify the receiver index if possible + } + assert!(asm.get_leaf_ccall()); // It checks the stack canary we set for known_cfunc_codegen. + + true +} + /// jit_save_pc() + gen_save_sp(). Should be used before calling a routine that could: /// - Perform GC allocation /// - Take the VM lock through RB_VM_LOCK_ENTER() @@ -5395,7 +5443,7 @@ fn jit_rb_str_byteslice( asm: &mut Assembler, _ocb: &mut OutlinedCb, _ci: *const rb_callinfo, - _cme: *const rb_callable_method_entry_t, + cme: *const rb_callable_method_entry_t, _block: Option, argc: i32, _known_recv_class: Option, @@ -5409,7 +5457,9 @@ fn jit_rb_str_byteslice( (Type::Fixnum, Type::Fixnum) => {}, // Raises when non-integers are passed in, which requires the method frame // to be pushed for the backtrace - _ => return false, + _ => if !jit_prepare_lazy_frame_call(jit, asm, cme, StackOpnd(2)) { + return false; + } } asm_comment!(asm, "String#byteslice"); @@ -5431,11 +5481,11 @@ fn jit_rb_str_byteslice( } fn jit_rb_str_getbyte( - _jit: &mut JITState, + jit: &mut JITState, asm: &mut Assembler, _ocb: &mut OutlinedCb, _ci: *const rb_callinfo, - _cme: *const rb_callable_method_entry_t, + cme: *const rb_callable_method_entry_t, _block: Option, _argc: i32, _known_recv_class: Option, @@ -5444,17 +5494,19 @@ fn jit_rb_str_getbyte( fn rb_str_getbyte(str: VALUE, index: VALUE) -> VALUE; } - let index = asm.stack_opnd(0); - let recv = asm.stack_opnd(1); - // rb_str_getbyte should be leaf if the index is a fixnum - if asm.ctx.get_opnd_type(index.into()) != Type::Fixnum { + if asm.ctx.get_opnd_type(StackOpnd(0)) != Type::Fixnum { // Raises when non-integers are passed in, which requires the method frame // to be pushed for the backtrace - return false; + if !jit_prepare_lazy_frame_call(jit, asm, cme, StackOpnd(1)) { + return false; + } } asm_comment!(asm, "String#getbyte"); + let index = asm.stack_opnd(0); + let recv = asm.stack_opnd(1); + let ret_opnd = asm.ccall(rb_str_getbyte as *const u8, vec![recv, index]); asm.stack_pop(2); // Keep them on stack during ccall for GC @@ -5465,6 +5517,35 @@ fn jit_rb_str_getbyte( true } +fn jit_rb_str_setbyte( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, + _ci: *const rb_callinfo, + cme: *const rb_callable_method_entry_t, + _block: Option, + _argc: i32, + _known_recv_class: Option, +) -> bool { + // Raises when index is out of range. Lazily push a frame in that case. + if !jit_prepare_lazy_frame_call(jit, asm, cme, StackOpnd(2)) { + return false; + } + asm_comment!(asm, "String#setbyte"); + + let value = asm.stack_opnd(0); + let index = asm.stack_opnd(1); + let recv = asm.stack_opnd(2); + + let ret_opnd = asm.ccall(rb_str_setbyte as *const u8, vec![recv, index, value]); + asm.stack_pop(3); // Keep them on stack during ccall for GC + + let out_opnd = asm.stack_push(Type::UnknownImm); + asm.mov(out_opnd, ret_opnd); + + true +} + // Codegen for rb_str_to_s() // When String#to_s is called on a String instance, the method returns self and // most of the overhead comes from setting up the method call. We observed that @@ -9693,6 +9774,7 @@ pub fn yjit_reg_method_codegen_fns() { yjit_reg_method(rb_cString, "size", jit_rb_str_length); yjit_reg_method(rb_cString, "bytesize", jit_rb_str_bytesize); yjit_reg_method(rb_cString, "getbyte", jit_rb_str_getbyte); + yjit_reg_method(rb_cString, "setbyte", jit_rb_str_setbyte); yjit_reg_method(rb_cString, "byteslice", jit_rb_str_byteslice); yjit_reg_method(rb_cString, "<<", jit_rb_str_concat); yjit_reg_method(rb_cString, "+@", jit_rb_str_uplus); @@ -9769,6 +9851,10 @@ pub struct CodegenGlobals { /// Page indexes for outlined code that are not associated to any ISEQ. ocb_pages: Vec, + + /// Map of cfunc YARV PCs to CMEs and receiver indexes, used to lazily push + /// a frame when rb_yjit_lazy_push_frame() is called with a PC in this HashMap. + pc_to_cfunc: HashMap<*mut VALUE, (*const rb_callable_method_entry_t, u8)>, } /// For implementing global code invalidation. A position in the inline @@ -9860,6 +9946,7 @@ impl CodegenGlobals { entry_stub_hit_trampoline, global_inval_patches: Vec::new(), ocb_pages, + pc_to_cfunc: HashMap::new(), }; // Initialize the codegen globals instance @@ -9938,6 +10025,10 @@ impl CodegenGlobals { pub fn get_ocb_pages() -> &'static Vec { &CodegenGlobals::get_instance().ocb_pages } + + pub fn get_pc_to_cfunc() -> &'static mut HashMap<*mut VALUE, (*const rb_callable_method_entry_t, u8)> { + &mut CodegenGlobals::get_instance().pc_to_cfunc + } } #[cfg(test)] diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index 488d4798a2a33f..e23f755388df47 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -117,6 +117,7 @@ extern "C" { ci: *const rb_callinfo, ) -> *const rb_callable_method_entry_t; pub fn rb_hash_empty_p(hash: VALUE) -> VALUE; + pub fn rb_str_setbyte(str: VALUE, index: VALUE, value: VALUE) -> VALUE; pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE; pub fn rb_vm_concat_array(ary1: VALUE, ary2st: VALUE) -> VALUE; pub fn rb_vm_concat_to_array(ary1: VALUE, ary2st: VALUE) -> VALUE; @@ -142,6 +143,7 @@ extern "C" { ) -> VALUE; pub fn rb_vm_ic_hit_p(ic: IC, reg_ep: *const VALUE) -> bool; pub fn rb_vm_stack_canary() -> VALUE; + pub fn rb_vm_push_cfunc_frame(cme: *const rb_callable_method_entry_t, recv_idx: c_int); } // Renames diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 3637de1613c0aa..6cdf1d0616a2e4 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -583,6 +583,11 @@ make_counters! { num_throw_retry, num_throw_return, + num_lazy_frame_check, + num_lazy_frame_push, + lazy_frame_count, + lazy_frame_failure, + iseq_stack_too_large, iseq_too_long, diff --git a/yjit/src/yjit.rs b/yjit/src/yjit.rs index 66d802ec5e6ee7..cc2c8fe0663195 100644 --- a/yjit/src/yjit.rs +++ b/yjit/src/yjit.rs @@ -207,3 +207,19 @@ pub extern "C" fn rb_yjit_simulate_oom_bang(_ec: EcPtr, _ruby_self: VALUE) -> VA return Qnil; } + +/// Push a C method frame if the given PC is supposed to lazily push one. +/// This is called from rb_raise() (at rb_exc_new_str()) and other functions +/// that may make a method call (e.g. rb_to_int()). +#[no_mangle] +pub extern "C" fn rb_yjit_lazy_push_frame(pc: *mut VALUE) { + if !yjit_enabled_p() { + return; + } + + incr_counter!(num_lazy_frame_check); + if let Some(&(cme, recv_idx)) = CodegenGlobals::get_pc_to_cfunc().get(&pc) { + incr_counter!(num_lazy_frame_push); + unsafe { rb_vm_push_cfunc_frame(cme, recv_idx as i32) } + } +} From ce8531fed4c7295aee94d24124914441db578136 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 23 Feb 2024 11:05:51 -0500 Subject: [PATCH 041/147] Stop using rb_str_locktmp_ensure publicly rb_str_locktmp_ensure is a private API. --- ext/socket/init.c | 3 ++- string.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/socket/init.c b/ext/socket/init.c index dd1158e19d2252..0e312b540e88cf 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -204,7 +204,8 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from) rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); #endif - slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, (VALUE)&arg); + rb_str_locktmp(str); + slen = (long)rb_ensure(recvfrom_locktmp, (VALUE)&arg, rb_str_unlocktmp, str); if (slen == 0 && !rsock_is_dgram(fptr)) { return Qnil; diff --git a/string.c b/string.c index d8b145db06a5fa..d9182530edebe5 100644 --- a/string.c +++ b/string.c @@ -3097,7 +3097,7 @@ rb_str_unlocktmp(VALUE str) return str; } -RUBY_FUNC_EXPORTED VALUE +VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg) { rb_str_locktmp(str); From ec6532b458b34e907a2474bab70642414bbb0d05 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 14:43:20 -0500 Subject: [PATCH 042/147] [ruby/prism] Add some encoding debugging to make testing easier https://github.com/ruby/prism/commit/0c042561c6 --- lib/prism/debug.rb | 43 +++++++++++++++++++++++ prism/extension.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb index c888436e4d1ef1..553205a04be375 100644 --- a/lib/prism/debug.rb +++ b/lib/prism/debug.rb @@ -202,5 +202,48 @@ def self.prism_locals(source) def self.newlines(source) Prism.parse(source).source.offsets end + + # A wrapping around prism's internal encoding data structures. This is used + # for reflection and debugging purposes. + class Encoding + # The name of the encoding, that can be passed to Encoding.find. + attr_reader :name + + # Initialize a new encoding with the given name and whether or not it is + # a multibyte encoding. + def initialize(name, multibyte) + @name = name + @multibyte = multibyte + end + + # Whether or not the encoding is a multibyte encoding. + def multibyte? + @multibyte + end + + # Returns the number of bytes of the first character in the source string, + # if it is valid for the encoding. Otherwise, returns 0. + def width(source) + Encoding._width(name, source) + end + + # Returns true if the first character in the source string is a valid + # alphanumeric character for the encoding. + def alnum?(source) + Encoding._alnum?(name, source) + end + + # Returns true if the first character in the source string is a valid + # alphabetic character for the encoding. + def alpha?(source) + Encoding._alpha?(name, source) + end + + # Returns true if the first character in the source string is a valid + # uppercase character for the encoding. + def upper?(source) + Encoding._upper?(name, source) + end + end end end diff --git a/prism/extension.c b/prism/extension.c index fd2281fd79747b..3eccb20e5a1d69 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -21,6 +21,8 @@ VALUE rb_cPrismParseError; VALUE rb_cPrismParseWarning; VALUE rb_cPrismParseResult; +VALUE rb_cPrismDebugEncoding; + ID rb_option_id_filepath; ID rb_option_id_encoding; ID rb_option_id_line; @@ -1102,6 +1104,80 @@ format_errors(VALUE self, VALUE source, VALUE colorize) { return result; } +/** + * call-seq: Debug::Encoding.all -> Array[Debug::Encoding] + * + * Return an array of all of the encodings that prism knows about. + */ +static VALUE +encoding_all(VALUE self) { + VALUE encodings = rb_ary_new(); + + for (size_t index = 0; index < PM_ENCODING_MAXIMUM; index++) { + const pm_encoding_t *encoding = &pm_encodings[index]; + + VALUE encoding_argv[] = { rb_str_new_cstr(encoding->name), encoding->multibyte ? Qtrue : Qfalse }; + rb_ary_push(encodings, rb_class_new_instance(2, encoding_argv, rb_cPrismDebugEncoding)); + } + + return encodings; +} + +static const pm_encoding_t * +encoding_find(VALUE name) { + const uint8_t *source = (const uint8_t *) RSTRING_PTR(name); + size_t length = RSTRING_LEN(name); + + const pm_encoding_t *encoding = pm_encoding_find(source, source + length); + if (encoding == NULL) { rb_raise(rb_eArgError, "Unknown encoding: %s", source); } + + return encoding; +} + +/** + * call-seq: Debug::Encoding.width(source) -> Integer + * + * Returns the width of the first character in the given string if it is valid + * in the encoding. If it is not, this function returns 0. + */ +static VALUE +encoding_char_width(VALUE self, VALUE name, VALUE value) { + return ULONG2NUM(encoding_find(name)->char_width((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value))); +} + +/** + * call-seq: Debug::Encoding.alnum?(source) -> true | false + * + * Returns true if the first character in the given string is an alphanumeric + * character in the encoding. + */ +static VALUE +encoding_alnum_char(VALUE self, VALUE name, VALUE value) { + return encoding_find(name)->alnum_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse; +} + +/** + * call-seq: Debug::Encoding.alpha?(source) -> true | false + * + * Returns true if the first character in the given string is an alphabetic + * character in the encoding. + */ +static VALUE +encoding_alpha_char(VALUE self, VALUE name, VALUE value) { + return encoding_find(name)->alpha_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse; +} + +/** + * call-seq: Debug::Encoding.upper?(source) -> true | false + * + * Returns true if the first character in the given string is an uppercase + * character in the encoding. + */ +static VALUE +encoding_isupper_char(VALUE self, VALUE name, VALUE value) { + return encoding_find(name)->isupper_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) ? Qtrue : Qfalse; +} + /******************************************************************************/ /* Initialization of the extension */ /******************************************************************************/ @@ -1182,6 +1258,15 @@ Init_prism(void) { rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2); + // Next, define the functions that are exposed through the private + // Debug::Encoding class. + rb_cPrismDebugEncoding = rb_define_class_under(rb_cPrismDebug, "Encoding", rb_cObject); + rb_define_singleton_method(rb_cPrismDebugEncoding, "all", encoding_all, 0); + rb_define_singleton_method(rb_cPrismDebugEncoding, "_width", encoding_char_width, 2); + rb_define_singleton_method(rb_cPrismDebugEncoding, "_alnum?", encoding_alnum_char, 2); + rb_define_singleton_method(rb_cPrismDebugEncoding, "_alpha?", encoding_alpha_char, 2); + rb_define_singleton_method(rb_cPrismDebugEncoding, "_upper?", encoding_isupper_char, 2); + // Next, initialize the other APIs. Init_prism_api_node(); Init_prism_pack(); From e45849419427963a353b2580d9ae4c4faaf2f3ba Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Fri, 23 Feb 2024 14:53:39 -0600 Subject: [PATCH 043/147] [DOC] Doc for command line options (#10059) --- doc/command_line/environment.md | 173 ++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 doc/command_line/environment.md diff --git a/doc/command_line/environment.md b/doc/command_line/environment.md new file mode 100644 index 00000000000000..abdfd5cfeb4121 --- /dev/null +++ b/doc/command_line/environment.md @@ -0,0 +1,173 @@ +## Environment + +Certain command-line options affect the execution environment +of the invoked Ruby program. + +### About the Examples + +The examples here use command-line option `-e`, +which passes the Ruby code to be executed on the command line itself: + +```sh +$ ruby -e 'puts "Hello, World."' +``` + +### Option `-C` + +The argument to option `-C` specifies a working directory +for the invoked Ruby program; +does not change the working directory for the current process: + +```sh +$ basename `pwd` +ruby +$ ruby -C lib -e 'puts File.basename(Dir.pwd)' +lib +$ basename `pwd` +ruby +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-I` + +The argument to option `-I` specifies a directory +to be added to the array in global variable `$LOAD_PATH`; +the option may be given more than once: + +```sh +$ pushd /tmp +$ ruby -e 'p $LOAD_PATH.size' +8 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size' +10 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)' +["/tmp/my_lib", "/tmp/some_lib"] +$ popd +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-r` + +The argument to option `-r` specifies a library to be required +before executing the Ruby program; +the option may be given more than once: + +```sh +$ ruby -e 'p defined?(JSON); p defined?(CSV)' +nil +nil +$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)' +"constant" +"constant" +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-0` + +Option `-0` defines the input record separator `$/` +for the invoked Ruby program. + +The optional argument to the option must be octal digits, +each in the range `0..7`; +these digits are prefixed with digit `0` to form an octal value: + +- If no argument is given, the input record separator is `0x00`. +- If the argument is `0`, the input record separator is `''`; + see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]. +- If the argument is in range `(1..0377)`, + it becomes the character value of the input record separator `$/`. +- Otherwise, the input record separator is `nil`. + +Examples: + +```sh +$ ruby -0 -e 'p $/' +"\x00" +ruby -00 -e 'p $/' +"" +$ ruby -012 -e 'p $/' +"\n" +$ ruby -015 -e 'p $/' +"\r" +$ ruby -0377 -e 'p $/' +"\xFF" +$ ruby -0400 -e 'p $/' +nil +``` + +The option may not be separated from its argument by whitespace. + +### Option `-d` + +Some code in (or called by) the Ruby program may include statements or blocks +conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`); +these commonly write to `$stdout` or `$stderr`. + +The default value for `$DEBUG` is `false`; +option `-d` (or `--debug`) sets it to `true`: + +```sh +$ ruby -e 'p $DEBUG' +false +$ ruby -d -e 'p $DEBUG' +true +``` + +### Option '-w' + +Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter). + +### Option `-W` + +Any Ruby code can create a warning message by calling method Kernel#warn; +methods in the Ruby core and standard libraries can also create warning messages. +Such a message may be printed on `$stderr` +(or not, depending on certain settings). + +Option `-W` helps determine whether a particular warning message +will be written, +by setting the initial value of global variable `$-W`: + +- `-W0`: Sets `$-W` to `0` (silent; no warnings). +- `-W1`: Sets `$-W` to `1` (moderate verbosity). +- `-W2`: Sets `$-W` to `2` (high verbosity). +- `-W`: Same as `-W2` (high verbosity). +- Option not given: Same as `-W1` (moderate verbosity). + +The value of `$-W`, in turn, determines which warning messages (if any) +are to be printed to `$stdout` (see Kernel#warn): + +```sh +$ ruby -W1 -e 'p $foo' +nil +$ ruby -W2 -e 'p $foo' +-e:1: warning: global variable '$foo' not initialized +nil +``` + +Ruby code may also define warnings for certain categories; +these are the default settings for the defined categories: + +``` +Warning[:experimental] # => true +Warning[:deprecated] # => false +Warning[:performance] # => false +``` + +They may also be set: +``` +Warning[:experimental] = false +Warning[:deprecated] = true +Warning[:performance] = true +``` + +You can suppress a category by prefixing `no-` to the category name: + +``` +$ ruby -W:no-experimental -e 'p IO::Buffer.new' +# +``` + From 96907f94953d0fac3ca518f755b54ea5098ae5eb Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 14:15:18 -0500 Subject: [PATCH 044/147] [ruby/prism] Convert pm_integer_t to strings https://github.com/ruby/prism/commit/fa9a30ad91 --- prism/extension.c | 21 ++++-- prism/templates/src/node.c.erb | 23 +----- prism/templates/src/prettyprint.c.erb | 31 +------- prism/util/pm_integer.c | 105 ++++++++++++++++++++++++++ prism/util/pm_integer.h | 9 +++ test/prism/integer_parse_test.rb | 4 +- 6 files changed, 137 insertions(+), 56 deletions(-) diff --git a/prism/extension.c b/prism/extension.c index 3eccb20e5a1d69..d0ffa2f9361a0a 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -953,9 +953,10 @@ named_captures(VALUE self, VALUE source) { /** * call-seq: - * Debug::integer_parse(source) -> Integer + * Debug::integer_parse(source) -> [Integer, String] * - * Parses the given source string and returns the integer it represents. + * Parses the given source string and returns the integer it represents, as well + * as a decimal string representation. */ static VALUE integer_parse(VALUE self, VALUE source) { @@ -965,17 +966,27 @@ integer_parse(VALUE self, VALUE source) { pm_integer_t integer = { 0 }; pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length); - VALUE result = UINT2NUM(integer.head.value); + VALUE number = UINT2NUM(integer.head.value); size_t shift = 0; for (pm_integer_word_t *node = integer.head.next; node != NULL; node = node->next) { VALUE receiver = rb_funcall(UINT2NUM(node->value), rb_intern("<<"), 1, ULONG2NUM(++shift * 32)); - result = rb_funcall(receiver, rb_intern("|"), 1, result); + number = rb_funcall(receiver, rb_intern("|"), 1, number); } - if (integer.negative) result = rb_funcall(result, rb_intern("-@"), 0); + if (integer.negative) number = rb_funcall(number, rb_intern("-@"), 0); + + pm_buffer_t buffer = { 0 }; + pm_integer_string(&buffer, &integer); + + VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer)); + pm_buffer_free(&buffer); pm_integer_free(&integer); + VALUE result = rb_ary_new_capa(2); + rb_ary_push(result, number); + rb_ary_push(result, string); + return result; } diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index 554645c3e78629..f9c58c82e12393 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -277,28 +277,7 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no <%- end -%> pm_buffer_append_byte(buffer, ']'); <%- when Prism::IntegerField -%> - { - const pm_integer_t *integer = &cast-><%= field.name %>; - if (integer->length == 0) { - if (integer->negative) pm_buffer_append_byte(buffer, '-'); - pm_buffer_append_string(buffer, "%" PRIu32, integer->head.value); - } else if (integer->length == 1) { - if (integer->negative) pm_buffer_append_byte(buffer, '-'); - pm_buffer_append_format(buffer, "%" PRIu64, ((uint64_t) integer->head.value) | (((uint64_t) integer->head.next->value) << 32)); - } else { - pm_buffer_append_byte(buffer, '{'); - pm_buffer_append_format(buffer, "\"negative\": %s", integer->negative ? "true" : "false"); - pm_buffer_append_string(buffer, ",\"values\":[", 11); - - const pm_integer_word_t *node = &integer->head; - while (node != NULL) { - pm_buffer_append_format(buffer, "%" PRIu32, node->value); - node = node->next; - if (node != NULL) pm_buffer_append_byte(buffer, ','); - } - pm_buffer_append_string(buffer, "]}", 2); - } - } + pm_integer_string(buffer, &cast-><%= field.name %>); <%- when Prism::DoubleField -%> pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>); <%- else -%> diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index 67a2f444e65fa6..2278d0d38ca4c0 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -128,34 +128,9 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm pm_buffer_append_byte(output_buffer, '\n'); <%- when Prism::IntegerField -%> const pm_integer_t *integer = &cast-><%= field.name %>; - if (integer->length == 0) { - pm_buffer_append_byte(output_buffer, ' '); - if (integer->negative) pm_buffer_append_byte(output_buffer, '-'); - pm_buffer_append_format(output_buffer, "%" PRIu32 "\n", integer->head.value); - } else if (integer->length == 1) { - pm_buffer_append_byte(output_buffer, ' '); - if (integer->negative) pm_buffer_append_byte(output_buffer, '-'); - pm_buffer_append_format(output_buffer, "%" PRIu64 "\n", ((uint64_t) integer->head.value) | (((uint64_t) integer->head.next->value) << 32)); - } else { - pm_buffer_append_byte(output_buffer, ' '); - - const pm_integer_word_t *node = &integer->head; - uint32_t index = 0; - - while (node != NULL) { - if (index != 0) pm_buffer_append_string(output_buffer, " | ", 3); - pm_buffer_append_format(output_buffer, "%" PRIu32, node->value); - - if (index != 0) { - pm_buffer_append_string(output_buffer, " << ", 4); - pm_buffer_append_format(output_buffer, "%" PRIu32, index * 32); - } - - node = node->next; - index++; - } - pm_buffer_append_string(output_buffer, "]\n", 2); - } + pm_buffer_append_byte(output_buffer, ' '); + pm_integer_string(output_buffer, integer); + pm_buffer_append_byte(output_buffer, '\n'); <%- when Prism::DoubleField -%> pm_buffer_append_format(output_buffer, " %f\n", cast-><%= field.name %>); <%- else -%> diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c index e39108a05b2728..98a09243ffafc6 100644 --- a/prism/util/pm_integer.c +++ b/prism/util/pm_integer.c @@ -14,6 +14,31 @@ pm_integer_node_create(pm_integer_t *integer, uint32_t value) { return node; } +/** + * Copy one integer onto another. + */ +static void +pm_integer_copy(pm_integer_t *dest, const pm_integer_t *src) { + dest->negative = src->negative; + dest->length = 0; + + dest->head.value = src->head.value; + dest->head.next = NULL; + + pm_integer_word_t *dest_current = &dest->head; + const pm_integer_word_t *src_current = src->head.next; + + while (src_current != NULL) { + dest_current->next = pm_integer_node_create(dest, src_current->value); + if (dest_current->next == NULL) return; + + dest_current = dest_current->next; + src_current = src_current->next; + } + + dest_current->next = NULL; +} + /** * Add a 32-bit integer to an integer. */ @@ -58,6 +83,37 @@ pm_integer_multiply(pm_integer_t *integer, uint32_t multiplier) { } } +/** + * Divide an individual word by a 32-bit integer. This will recursively divide + * any subsequent nodes in the linked list. + */ +static uint32_t +pm_integer_divide_word(pm_integer_t *integer, pm_integer_word_t *word, uint32_t dividend) { + uint32_t remainder = 0; + if (word->next != NULL) { + remainder = pm_integer_divide_word(integer, word->next, dividend); + + if (integer->length > 0 && word->next->value == 0) { + free(word->next); + word->next = NULL; + integer->length--; + } + } + + uint64_t value = ((uint64_t) remainder << 32) | word->value; + word->value = (uint32_t) (value / dividend); + return (uint32_t) (value % dividend); +} + +/** + * Divide an integer by a 32-bit integer. In practice, this is only 10 so that + * we can format it as a string. It returns the remainder of the division. + */ +static uint32_t +pm_integer_divide(pm_integer_t *integer, uint32_t dividend) { + return pm_integer_divide_word(integer, &integer->head, dividend); +} + /** * Return the value of a digit in a uint32_t. */ @@ -177,6 +233,55 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) { return 0; } +/** + * Convert an integer to a decimal string. + */ +PRISM_EXPORTED_FUNCTION void +pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer) { + if (integer->negative) { + pm_buffer_append_byte(buffer, '-'); + } + + switch (integer->length) { + case 0: { + const uint32_t value = integer->head.value; + pm_buffer_append_format(buffer, "%" PRIu32, value); + return; + } + case 1: { + const uint64_t value = ((uint64_t) integer->head.value) | (((uint64_t) integer->head.next->value) << 32); + pm_buffer_append_format(buffer, "%" PRIu64, value); + return; + } + default: { + // First, allocate a buffer that we'll copy the decimal digits into. + size_t length = (integer->length + 1) * 10; + char *digits = calloc(length, sizeof(char)); + if (digits == NULL) return; + + // Next, create a new integer that we'll use to store the result of + // the division and modulo operations. + pm_integer_t copy; + pm_integer_copy(©, integer); + + // Then, iterate through the integer, dividing by 10 and storing the + // result in the buffer. + char *ending = digits + length - 1; + char *current = ending; + + while (copy.length > 0 || copy.head.value > 0) { + uint32_t remainder = pm_integer_divide(©, 10); + *current-- = (char) ('0' + remainder); + } + + // Finally, append the string to the buffer and free the digits. + pm_buffer_append_string(buffer, current + 1, (size_t) (ending - current)); + free(digits); + return; + } + } +} + /** * Recursively destroy the linked list of an integer. */ diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h index a80db633bbebd1..4e080870ae2cdc 100644 --- a/prism/util/pm_integer.h +++ b/prism/util/pm_integer.h @@ -7,6 +7,7 @@ #define PRISM_NUMBER_H #include "prism/defines.h" +#include "prism/util/pm_buffer.h" #include #include @@ -104,6 +105,14 @@ size_t pm_integer_memsize(const pm_integer_t *integer); */ int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right); +/** + * Convert an integer to a decimal string. + * + * @param buffer The buffer to append the string to. + * @param integer The integer to convert to a string. + */ +PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer); + /** * Free the internal memory of an integer. This memory will only be allocated if * the integer exceeds the size of a single node in the linked list. diff --git a/test/prism/integer_parse_test.rb b/test/prism/integer_parse_test.rb index 756f667b965c5d..afc3806fe63046 100644 --- a/test/prism/integer_parse_test.rb +++ b/test/prism/integer_parse_test.rb @@ -31,7 +31,9 @@ def test_integer_parse private def assert_integer_parse(expected, source = expected.to_s) - assert_equal expected, Debug.integer_parse(source) + integer, string = Debug.integer_parse(source) + assert_equal expected, integer + assert_equal expected.to_s, string end end end From a255b43ff11ed06519ba0224cc6cbb2626969666 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 23 Feb 2024 17:17:12 -0500 Subject: [PATCH 045/147] Update common.mk --- common.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/common.mk b/common.mk index f9d16b4ea2de6c..9aefa02105419d 100644 --- a/common.mk +++ b/common.mk @@ -12320,9 +12320,12 @@ prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/diagnostic.$(OBJEXT): {$(VPATH)}config.h prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h @@ -12608,6 +12611,8 @@ prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h @@ -12664,8 +12669,11 @@ prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/token_type.$(OBJEXT): {$(VPATH)}config.h prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h @@ -12686,8 +12694,11 @@ prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/util/pm_constant_pool.$(OBJEXT): {$(VPATH)}config.h prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h @@ -12730,6 +12741,8 @@ prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h From e439419baaf298b562cfbf7d98d3ce1cf608ab08 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 23 Feb 2024 16:21:33 -0800 Subject: [PATCH 046/147] [DOC] Fix a typo --- yjit/src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 7148f4a4e60abb..41c7adae2c658d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -8278,7 +8278,7 @@ fn gen_send_general( mid = unsafe { rb_get_symbol_id(compile_time_name) }; if mid == 0 { - // This also rejects method names that need convserion + // This also rejects method names that need conversion gen_counter_incr(asm, Counter::send_send_null_mid); return None; } From fc656acee9d17f72d9f7b09630d7f03e981beef3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 21:56:56 -0500 Subject: [PATCH 047/147] [PRISM] Sync to latest prism --- prism/prism.c | 2 +- prism/templates/template.rb | 49 ++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index bf32cedc2c1753..864dd49f511b3d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9829,7 +9829,7 @@ parser_lex(pm_parser_t *parser) { ) { // Since we know we're about to add an __END__ comment, we know we - // need to add all of the newlines to get the correct column + // need at add all of the newlines to get the correct column // information for it. const uint8_t *cursor = parser->current.end; while ((cursor = next_newline(cursor, parser->end - cursor)) != NULL) { diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 12749add22d24e..2831b091878a71 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -10,6 +10,39 @@ module Prism JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby" JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String" + # This module contains methods for escaping characters in JavaDoc comments. + module JavaDoc + ESCAPES = { + "'" => "'", + "\"" => """, + "@" => "@", + "&" => "&", + "<" => "<", + ">" => ">" + }.freeze + + def self.escape(value) + value.gsub(/['&"<>@]/, ESCAPES) + end + end + + # A comment attached to a field or node. + class Comment + attr_reader :value + + def initialize(value) + @value = value + end + + def each_line(&block) + value.each_line { |line| yield line.prepend(" ").rstrip } + end + + def each_java_line(&block) + Comment.new(JavaDoc.escape(value)).each_line(&block) + end + end + # This represents a field on a node. It contains all of the necessary # information to template out the code for that field. class Field @@ -21,8 +54,12 @@ def initialize(name:, comment: nil, **options) @options = options end - def each_comment_line - comment.each_line { |line| yield line.prepend(" ").rstrip } if comment + def each_comment_line(&block) + Comment.new(comment).each_line(&block) if comment + end + + def each_comment_java_line(&block) + Comment.new(comment).each_java_line(&block) if comment end def semantic_field? @@ -317,8 +354,12 @@ def initialize(config) @comment = config.fetch("comment") end - def each_comment_line - comment.each_line { |line| yield line.prepend(" ").rstrip } + def each_comment_line(&block) + Comment.new(comment).each_line(&block) + end + + def each_comment_java_line(&block) + Comment.new(comment).each_java_line(&block) end def semantic_fields From b9b0712556980a3af91c976c3fee8ba0e21c39a0 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Mon, 18 Dec 2023 14:22:21 -0800 Subject: [PATCH 048/147] [ruby/prism] Use steep to type check RBS and Ruby files https://github.com/ruby/prism/commit/eabed9f4fd --- lib/prism/debug.rb | 6 ++-- lib/prism/desugar_compiler.rb | 2 +- lib/prism/lex_compat.rb | 32 +++++++++++--------- lib/prism/node_ext.rb | 4 +-- lib/prism/pack.rb | 2 ++ lib/prism/parse_result/comments.rb | 6 ++-- lib/prism/prism.gemspec | 20 +++++++++++- prism/templates/lib/prism/dot_visitor.rb.erb | 2 +- prism/templates/lib/prism/node.rb.erb | 4 +-- prism/templates/template.rb | 12 ++++++-- 10 files changed, 59 insertions(+), 31 deletions(-) diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb index 553205a04be375..74f824faa70d4f 100644 --- a/lib/prism/debug.rb +++ b/lib/prism/debug.rb @@ -55,7 +55,7 @@ def self.cruby_locals(source) verbose, $VERBOSE = $VERBOSE, nil begin - locals = [] + locals = [] #: Array[Array[Symbol | Integer]] stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)] while (iseq = stack.pop) @@ -96,8 +96,8 @@ def self.cruby_locals(source) # For the given source, parses with prism and returns a list of all of the # sets of local variables that were encountered. def self.prism_locals(source) - locals = [] - stack = [Prism.parse(source).value] + locals = [] #: Array[Array[Symbol | Integer]] + stack = [Prism.parse(source).value] #: Array[Prism::node] while (node = stack.pop) case node diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 00b3097f9f3e0b..8d059b0c989bcf 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -82,7 +82,7 @@ def compile 0, read_class.new(source, *arguments, node.name_loc), nil, - node.operator_loc.slice.chomp("="), + node.operator_loc.slice.chomp("=").to_sym, node.operator_loc.copy(length: node.operator_loc.length - 1), nil, ArgumentsNode.new(source, 0, [node.value], node.value.location), diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index c11903423d9276..3a0431841ee25d 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -185,6 +185,8 @@ class LexCompat # :nodoc: # However, we add a couple of convenience methods onto them to make them a # little easier to work with. We delegate all other methods to the array. class Token < SimpleDelegator + # @dynamic initialize, each, [] + # The location of the token in the source. def location self[0] @@ -241,10 +243,10 @@ class IgnoredNewlineToken < Token def ==(other) # :nodoc: return false unless self[0...-1] == other[0...-1] - if self[4] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED - other[4] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED > 0 + if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED + other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED > 0 else - self[4] == other[4] + self[3] == other[3] end end end @@ -308,7 +310,7 @@ def <<(token) def to_a embexpr_balance = 0 - tokens.each_with_object([]) do |token, results| + tokens.each_with_object([]) do |token, results| #$ Array[Token] case token.event when :on_embexpr_beg embexpr_balance += 1 @@ -409,7 +411,7 @@ def to_a # If every line in the heredoc is blank, we still need to split up the # string content token into multiple tokens. if dedent.nil? - results = [] + results = [] #: Array[Token] embexpr_balance = 0 tokens.each do |token| @@ -444,7 +446,7 @@ def to_a # If the minimum common whitespace is 0, then we need to concatenate # string nodes together that are immediately adjacent. if dedent == 0 - results = [] + results = [] #: Array[Token] embexpr_balance = 0 index = 0 @@ -477,7 +479,7 @@ def to_a # insert on_ignored_sp tokens for the amount of dedent that we need to # perform. We also need to remove the dedent from the beginning of # each line of plain string content tokens. - results = [] + results = [] #: Array[Token] dedent_next = true embexpr_balance = 0 @@ -526,7 +528,7 @@ def to_a # dedent from the beginning of the line. if (dedent > 0) && (dedent_next || index > 0) deleting = 0 - deleted_chars = [] + deleted_chars = [] #: Array[String] # Gather up all of the characters that we're going to # delete, stopping when you hit a character that would put @@ -603,15 +605,15 @@ def initialize(source, **options) end def result - tokens = [] + tokens = [] #: Array[LexCompat::Token] state = :default - heredoc_stack = [[]] + heredoc_stack = [[]] #: Array[Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc]] result = Prism.lex(source, **options) result_value = result.value - previous_state = nil - last_heredoc_end = nil + previous_state = nil #: Ripper::Lexer::State? + last_heredoc_end = nil #: Integer? # In previous versions of Ruby, Ripper wouldn't flush the bom before the # first token, so we had to have a hack in place to account for that. This @@ -842,7 +844,7 @@ def result # We sort by location to compare against Ripper's output tokens.sort_by!(&:location) - ParseResult.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, []) + ParseResult.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, Source.new(source)) end end @@ -858,8 +860,8 @@ def initialize(source) end def result - previous = [] - results = [] + previous = [] #: [[Integer, Integer], Symbol, String, untyped] | [] + results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]] lex(source).each do |token| case token[1] diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index c0f485f675de00..688e60a15957a6 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -169,7 +169,7 @@ def full_name class ParametersNode < Node # Mirrors the Method#parameters method. def signature - names = [] + names = [] #: Array[[:req | :opt | :rest | :keyreq | :key | :keyrest | :block, Symbol] | [:rest | :keyrest | :nokey]] requireds.each do |param| names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) @@ -184,7 +184,7 @@ def signature # Regardless of the order in which the keywords were defined, the required # keywords always come first followed by the optional keywords. - keyopt = [] + keyopt = [] #: Array[OptionalKeywordParameterNode] keywords.each do |param| if param.is_a?(OptionalKeywordParameterNode) keyopt << param diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb index 00caf553c60954..0168e5e7496ada 100644 --- a/lib/prism/pack.rb +++ b/lib/prism/pack.rb @@ -148,6 +148,8 @@ def describe end when LENGTH_MAX base + ", as many as possible" + else + raise end when UTF8 "UTF-8 character" diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index dd8fa8e1c7e3f7..0f1522deade01c 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -120,7 +120,7 @@ def nearest_targets(node, comment) comment_start = comment.location.start_offset comment_end = comment.location.end_offset - targets = [] + targets = [] #: Array[_Target] node.comment_targets.map do |value| case value when StatementsNode @@ -133,8 +133,8 @@ def nearest_targets(node, comment) end targets.sort_by!(&:start_offset) - preceding = nil - following = nil + preceding = nil #: _Target? + following = nil #: _Target? left = 0 right = targets.length diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index ac4bdddc21eb76..8e642192a5a07d 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -122,8 +122,26 @@ Gem::Specification.new do |spec| "src/options.c", "src/prism.c", "prism.gemspec", + "sig/manifest.yaml", "sig/prism.rbs", - "sig/prism_static.rbs", + "sig/prism/compiler.rbs", + "sig/prism/debug.rbs", + "sig/prism/desugar_compiler.rbs", + "sig/prism/dispatcher.rbs", + "sig/prism/dot_visitor.rbs", + "sig/prism/dsl.rbs", + "sig/prism/lex_compat.rbs", + "sig/prism/mutation_compiler.rbs", + "sig/prism/node_ext.rbs", + "sig/prism/node_inspector.rbs", + "sig/prism/node.rbs", + "sig/prism/pack.rbs", + "sig/prism/parse_result/comments.rbs", + "sig/prism/parse_result/newlines.rbs", + "sig/prism/pattern.rbs", + "sig/prism/ripper_compat.rbs", + "sig/prism/serialize.rbs", + "sig/prism/visitor.rbs", "rbi/prism.rbi", "rbi/prism_static.rbi" ] diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb index 1dc48d265ddd92..56f116b8d3944e 100644 --- a/prism/templates/lib/prism/dot_visitor.rb.erb +++ b/prism/templates/lib/prism/dot_visitor.rb.erb @@ -175,7 +175,7 @@ module Prism # Inspect a node that has <%= flag.human %> flags to display the flags as a # comma-separated list. def <%= flag.human %>_inspect(node) - flags = [] + flags = [] #: Array[String] <%- flag.values.each do |value| -%> flags << "<%= value.name.downcase %>" if node.<%= value.name.downcase %>? <%- end -%> diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 19fcda936fae56..99d89712cfb350 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -150,7 +150,7 @@ module Prism # def compact_child_nodes: () -> Array[Node] def compact_child_nodes <%- if node.fields.any? { |field| field.is_a?(Prism::OptionalNodeField) } -%> - compact = [] + compact = [] #: Array[Prism::node] <%- node.fields.each do |field| -%> <%- case field -%> <%- when Prism::NodeField -%> @@ -179,7 +179,7 @@ module Prism when Prism::NodeField, Prism::LocationField then field.name when Prism::OptionalNodeField, Prism::NodeListField, Prism::OptionalLocationField then "*#{field.name}" end - }.compact.join(", ") %>] + }.compact.join(", ") %>] #: Array[Prism::node | Location] end # def copy: (**params) -> <%= node.name %> diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 2831b091878a71..35133169fee2c5 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -103,7 +103,7 @@ def java_cast # references and store them as references. class NodeField < NodeKindField def rbs_class - ruby_type + options[:kind] || "Prism::node" end def rbi_class @@ -115,7 +115,7 @@ def rbi_class # optionally null. We pass them as references and store them as references. class OptionalNodeField < NodeKindField def rbs_class - "#{ruby_type}?" + "#{options[:kind] || "Prism::node"}?" end def rbi_class @@ -127,7 +127,7 @@ def rbi_class # references and store them directly on the struct. class NodeListField < Field def rbs_class - "Array[Node]" + "Array[Prism::node]" end def rbi_class @@ -549,6 +549,12 @@ def locals "src/token_type.c", "rbi/prism.rbi", "sig/prism.rbs", + "sig/prism/dot_visitor.rbs", + "sig/prism/dsl.rbs", + "sig/prism/mutation_compiler.rbs", + "sig/prism/node.rbs", + "sig/prism/ripper_compat.rbs", + "sig/prism/visitor.rbs", ] end From 46fe3dc799e937fcd369f6c22a038c9fc35a7328 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Wed, 20 Dec 2023 20:44:40 -0800 Subject: [PATCH 049/147] [ruby/prism] Fix IgnoredNewlineToken comparison of Ripper::Lexer::State https://github.com/ruby/prism/commit/8c9502f61b --- lib/prism/lex_compat.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb index 3a0431841ee25d..70cb0652018239 100644 --- a/lib/prism/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -244,7 +244,7 @@ def ==(other) # :nodoc: return false unless self[0...-1] == other[0...-1] if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED - other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED > 0 + other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED != 0 else self[3] == other[3] end From e03e9c3644c3c5a8713e1fed547da0c0becf36de Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Wed, 20 Dec 2023 20:41:52 -0800 Subject: [PATCH 050/147] [ruby/prism] wip: node unions https://github.com/ruby/prism/commit/99a71675d4 --- prism/config.yml | 32 ++++++++++++++++++++++++++++++++ prism/templates/template.rb | 34 +++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index af4bc42fb6104c..9a959c9cb88828 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -692,6 +692,7 @@ nodes: type: constant[] - name: parameters type: node? + kind: BlockParametersNode - name: body type: node? - name: opening_loc @@ -727,6 +728,7 @@ nodes: kind: ParametersNode - name: locals type: node[] + kind: BlockLocalVariableNode - name: opening_loc type: location? - name: closing_loc @@ -1134,6 +1136,9 @@ nodes: type: node? - name: child type: node + kind: + - ConstantReadNode + - MissingNode - name: delimiter_loc type: location comment: | @@ -1177,6 +1182,9 @@ nodes: type: node? - name: child type: node + kind: + - ConstantReadNode + - MissingNode - name: delimiter_loc type: location comment: | @@ -1617,6 +1625,10 @@ nodes: fields: - name: numeric type: node + kind: + - FloatNode + - IntegerNode + - RationalNode comment: | Represents an imaginary number literal. @@ -2370,16 +2382,36 @@ nodes: fields: - name: requireds type: node[] + kind: + - RequiredParameterNode + - MultiTargetNode - name: optionals type: node[] + kind: OptionalParameterNode - name: rest type: node? + kind: + - RestParameterNode + - ImplicitRestNode # Only in block parameters - name: posts type: node[] + kind: + - RequiredParameterNode + - MultiTargetNode + # On parsing error of `f(**kwargs, ...)` or `f(**nil, ...)`, the keyword_rest value is moved here: + - KeywordRestParameterNode + - NoKeywordsParameterNode - name: keywords type: node[] + kind: + - RequiredKeywordParameterNode + - OptionalKeywordParameterNode - name: keyword_rest type: node? + kind: + - KeywordRestParameterNode + - ForwardingParameterNode + - NoKeywordsParameterNode - name: block type: node? kind: BlockParameterNode diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 35133169fee2c5..18806901e1a777 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -75,35 +75,49 @@ def should_be_serialized? # node and not just a generic node. class NodeKindField < Field def c_type - if options[:kind] - "pm_#{options[:kind].gsub(/(?<=.)[A-Z]/, "_\\0").downcase}" + if specific_kind + "pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}" else "pm_node" end end def ruby_type - options[:kind] || "Node" + specific_kind || "Node" end def java_type - options[:kind] || "Node" + specific_kind || "Node" end def java_cast - if options[:kind] + if specific_kind "(Nodes.#{options[:kind]}) " else "" end end + + def specific_kind + @options[:kind] unless @options[:kind].is_a?(Array) + end + + def union_kind + options[:kind] if @options[:kind].is_a?(Array) + end end # This represents a field on a node that is itself a node. We pass them as # references and store them as references. class NodeField < NodeKindField def rbs_class - options[:kind] || "Prism::node" + if specific_kind + specific_kind + elsif union_kind + union_kind.join(" | ") + else + "Prism::node" + end end def rbi_class @@ -115,7 +129,13 @@ def rbi_class # optionally null. We pass them as references and store them as references. class OptionalNodeField < NodeKindField def rbs_class - "#{options[:kind] || "Prism::node"}?" + if specific_kind + "#{specific_kind}?" + elsif union_kind + [union_kind, "nil"].join(" | ") + else + "Prism::node?" + end end def rbi_class From 7556fd937cfedbee9775b92124fcdce5c416dd50 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Mon, 8 Jan 2024 10:31:37 -0800 Subject: [PATCH 051/147] [ruby/prism] Split private types https://github.com/ruby/prism/commit/0209d093ec --- lib/prism/node_ext.rb | 7 +++-- lib/prism/pack.rb | 1 + lib/prism/parse_result.rb | 12 +++------ lib/prism/parse_result/comments.rb | 1 + lib/prism/parse_result/newlines.rb | 6 ++++- lib/prism/pattern.rb | 22 +++++++++++++--- lib/prism/prism.gemspec | 9 ++----- prism/config.yml | 5 +++- prism/templates/lib/prism/dot_visitor.rb.erb | 2 +- prism/templates/lib/prism/node.rb.erb | 11 +++----- prism/templates/template.rb | 27 +++++++++++++++----- 11 files changed, 65 insertions(+), 38 deletions(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 688e60a15957a6..36a43b6327e4c9 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -169,14 +169,17 @@ def full_name class ParametersNode < Node # Mirrors the Method#parameters method. def signature - names = [] #: Array[[:req | :opt | :rest | :keyreq | :key | :keyrest | :block, Symbol] | [:rest | :keyrest | :nokey]] + names = [] #: Array[[:req | :opt | :rest | :keyreq | :key | :keyrest | :block, Symbol] | [:req | :rest | :keyrest | :nokey]] requireds.each do |param| names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) end optionals.each { |param| names << [:opt, param.name] } - names << [:rest, rest.name || :*] if rest + + if rest && rest.is_a?(RestParameterNode) + names << [:rest, rest.name || :*] + end posts.each do |param| names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb index 0168e5e7496ada..31c768612328bd 100644 --- a/lib/prism/pack.rb +++ b/lib/prism/pack.rb @@ -216,6 +216,7 @@ def describe else source = directive.source end + # @type var source_width: Integer " #{source.ljust(source_width)} #{directive.describe}" end diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 7cb982e69981f6..1d9e7008822faa 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -30,7 +30,7 @@ def encoding # Perform a byteslice on the source code using the given byte offset and # byte length. def slice(byte_offset, length) - source.byteslice(byte_offset, length) + source.byteslice(byte_offset, length) or raise end # Binary search through the offsets to find the line number for the given @@ -52,7 +52,7 @@ def column(byte_offset) # Return the character offset for the given byte offset. def character_offset(byte_offset) - source.byteslice(0, byte_offset).length + (source.byteslice(0, byte_offset) or raise).length end # Return the column number in characters for the given byte offset. @@ -157,12 +157,8 @@ def comments end # Create a new location object with the given options. - def copy(**options) - Location.new( - options.fetch(:source) { source }, - options.fetch(:start_offset) { start_offset }, - options.fetch(:length) { length } - ) + def copy(source: self.source, start_offset: self.start_offset, length: self.length) + Location.new(source, start_offset, length) end # Returns a string representation of this location. diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 0f1522deade01c..314261ea470721 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -150,6 +150,7 @@ def nearest_targets(node, comment) target_end = target.end_offset if target.encloses?(comment) + # @type var target: NodeTarget # The comment is completely contained by this target. Abandon the # binary search at this level. return nearest_targets(target.node, comment) diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index ca05f5b7026767..96c97646ff141a 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -58,7 +58,11 @@ def visit_statements_node(node) # Walk the tree and mark nodes that are on a new line. def mark_newlines! - value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) + if ProgramNode === value + value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) + else + raise "ParseResult does not contain ProgramNode value" + end end end end diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index e1643671ec1131..8e0d235796cd2b 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -69,7 +69,14 @@ def initialize(query) # nodes. def compile result = Prism.parse("case nil\nin #{query}\nend") - compile_node(result.value.statements.body.last.conditions.last.pattern) + + case_match_node = result.value.statements.body.last + raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode) + + in_node = case_match_node.conditions.last + raise CompilationError, in_node.inspect unless in_node.is_a?(InNode) + + compile_node(in_node.pattern) end # Scan the given node and all of its children for nodes that match the @@ -77,13 +84,14 @@ def compile # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. def scan(root) - return to_enum(__method__, root) unless block_given? + return to_enum(__method__ || raise, root) unless block_given? @compiled ||= compile + compiled = @compiled #: Proc queue = [root] while (node = queue.shift) - yield node if @compiled.call(node) + yield node if compiled.call(node) queue.concat(node.compact_child_nodes) end end @@ -174,7 +182,13 @@ def compile_hash_pattern_node(node) preprocessed = node.elements.to_h do |element| - [element.key.unescaped.to_sym, compile_node(element.value)] + key = element.key + if key.respond_to?(:unescaped) + # @type var key: SymbolNode + [key.unescaped.to_sym, compile_node(element.value)] + else + raise CompilationError, element.inspect + end end compiled_keywords = ->(other) do diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 8e642192a5a07d..16ae553e323501 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -125,19 +125,14 @@ Gem::Specification.new do |spec| "sig/manifest.yaml", "sig/prism.rbs", "sig/prism/compiler.rbs", - "sig/prism/debug.rbs", - "sig/prism/desugar_compiler.rbs", "sig/prism/dispatcher.rbs", "sig/prism/dot_visitor.rbs", "sig/prism/dsl.rbs", - "sig/prism/lex_compat.rbs", "sig/prism/mutation_compiler.rbs", - "sig/prism/node_ext.rbs", - "sig/prism/node_inspector.rbs", "sig/prism/node.rbs", + "sig/prism/node_ext.rbs", "sig/prism/pack.rbs", - "sig/prism/parse_result/comments.rbs", - "sig/prism/parse_result/newlines.rbs", + "sig/prism/parse_result.rbs", "sig/prism/pattern.rbs", "sig/prism/ripper_compat.rbs", "sig/prism/serialize.rbs", diff --git a/prism/config.yml b/prism/config.yml index 9a959c9cb88828..a89052d7699992 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -692,7 +692,6 @@ nodes: type: constant[] - name: parameters type: node? - kind: BlockParametersNode - name: body type: node? - name: opening_loc @@ -1583,8 +1582,12 @@ nodes: type: node? - name: elements type: node[] + kind: AssocNode - name: rest type: node? + kind: + - AssocSplatNode + - NoKeywordsParameterNode - name: opening_loc type: location? - name: closing_loc diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb index 56f116b8d3944e..5a9b4954442884 100644 --- a/prism/templates/lib/prism/dot_visitor.rb.erb +++ b/prism/templates/lib/prism/dot_visitor.rb.erb @@ -17,7 +17,7 @@ module Prism if port "#{name}" else - "#{name}#{CGI.escapeHTML(value)}" + "#{name}#{CGI.escapeHTML(value || raise)}" end end end diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 99d89712cfb350..98048989f29157 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -182,14 +182,9 @@ module Prism }.compact.join(", ") %>] #: Array[Prism::node | Location] end - # def copy: (**params) -> <%= node.name %> - def copy(**params) - <%= node.name %>.new( - source, - <%- (node.fields.map(&:name) + ["location"]).map do |name| -%> - params.fetch(:<%= name %>) { <%= name %> }, - <%- end -%> - ) + # def copy: (<%= (node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" } + ["?location: Location"]).join(", ") %>) -> <%= node.name %> + def copy(<%= (node.fields.map(&:name) + ["location"]).map { |field| "#{field}: self.#{field}" }.join(", ") %>) + <%= node.name %>.new(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>) end # def deconstruct: () -> Array[nil | Node] diff --git a/prism/templates/template.rb b/prism/templates/template.rb index 18806901e1a777..aba909bdc3b770 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -99,11 +99,11 @@ def java_cast end def specific_kind - @options[:kind] unless @options[:kind].is_a?(Array) + options[:kind] unless options[:kind].is_a?(Array) end def union_kind - options[:kind] if @options[:kind].is_a?(Array) + options[:kind] if options[:kind].is_a?(Array) end end @@ -132,7 +132,7 @@ def rbs_class if specific_kind "#{specific_kind}?" elsif union_kind - [union_kind, "nil"].join(" | ") + [*union_kind, "nil"].join(" | ") else "Prism::node?" end @@ -147,7 +147,13 @@ def rbi_class # references and store them directly on the struct. class NodeListField < Field def rbs_class - "Array[Prism::node]" + if specific_kind + "Array[#{specific_kind}]" + elsif union_kind + "Array[#{union_kind.join(" | ")}]" + else + "Array[Prism::node]" + end end def rbi_class @@ -157,6 +163,15 @@ def rbi_class def java_type "Node[]" end + + # TODO: unduplicate with NodeKindField + def specific_kind + options[:kind] unless options[:kind].is_a?(Array) + end + + def union_kind + options[:kind] if options[:kind].is_a?(Array) + end end # This represents a field on a node that is the ID of a string interned @@ -569,12 +584,12 @@ def locals "src/token_type.c", "rbi/prism.rbi", "sig/prism.rbs", - "sig/prism/dot_visitor.rbs", "sig/prism/dsl.rbs", "sig/prism/mutation_compiler.rbs", "sig/prism/node.rbs", - "sig/prism/ripper_compat.rbs", "sig/prism/visitor.rbs", + "sig/prism/_private/dot_visitor.rbs", + "sig/prism/_private/ripper_compat.rbs", ] end From 935d4fab62eb2c578508d8d3cfcd0f726b965db6 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Mon, 8 Jan 2024 15:28:17 -0800 Subject: [PATCH 052/147] [ruby/prism] Remove Ripper from public RBS, type-assert remaining issues https://github.com/ruby/prism/commit/5fda7a0760 --- lib/prism/node_ext.rb | 47 +++-- lib/prism/parse_result.rb | 3 +- lib/prism/parse_result/comments.rb | 7 +- lib/prism/prism.gemspec | 1 - lib/prism/ripper_compat.rb | 208 +++++++++++++++++++++++ prism/templates/lib/prism/dsl.rb.erb | 1 + prism/templates/lib/prism/node.rb.erb | 1 + prism/templates/lib/prism/visitor.rb.erb | 3 + 8 files changed, 255 insertions(+), 16 deletions(-) create mode 100644 lib/prism/ripper_compat.rb diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 36a43b6327e4c9..fdd6ac200d229d 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -106,14 +106,23 @@ class ConstantPathNode < Node # local variable class DynamicPartsInConstantPathError < StandardError; end + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError; end + # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] def full_name_parts - parts = [child.name] - current = parent + parts = [] #: Array[Symbol] + current = self #: node? while current.is_a?(ConstantPathNode) - parts.unshift(current.child.name) + child = current.child + if child.is_a?(MissingNode) + raise MissingNodesInConstantPathError, "Constant path contains missing nodes. Cannot compute full name" + end + parts.unshift(child.name) current = current.parent end @@ -134,14 +143,19 @@ class ConstantPathTargetNode < Node # Returns the list of parts for the full name of this constant path. # For example: [:Foo, :Bar] def full_name_parts - parts = case parent - when ConstantPathNode, ConstantReadNode - parent.full_name_parts - when nil - [:""] - else - raise ConstantPathNode::DynamicPartsInConstantPathError, - "Constant path target contains dynamic parts. Cannot compute full name" + parts = + case parent + when ConstantPathNode, ConstantReadNode + parent.full_name_parts + when nil + [:""] + else + # e.g. self::Foo, (var)::Bar = baz + raise ConstantPathNode::DynamicPartsInConstantPathError, "Constant target path contains dynamic parts. Cannot compute full name" + end + + if child.is_a?(MissingNode) + raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name" end parts.push(child.name) @@ -169,7 +183,7 @@ def full_name class ParametersNode < Node # Mirrors the Method#parameters method. def signature - names = [] #: Array[[:req | :opt | :rest | :keyreq | :key | :keyrest | :block, Symbol] | [:req | :rest | :keyrest | :nokey]] + names = [] #: Array[[Symbol, Symbol] | [Symbol]] requireds.each do |param| names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) @@ -182,7 +196,14 @@ def signature end posts.each do |param| - names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) + if param.is_a?(MultiTargetNode) + names << [:req] + elsif param.is_a?(NoKeywordsParameterNode) + # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts + raise "Invalid syntax" + else + names << [:req, param.name] + end end # Regardless of the order in which the keywords were defined, the required diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 1d9e7008822faa..c55b7b6685cf60 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -281,7 +281,8 @@ def join(other) # the beginning of the file. Useful for when you want a location object but # do not care where it points. def self.null - new(nil, 0, 0) + source = nil #: Source + new(source, 0, 0) end end diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 314261ea470721..4e1b9a68e572de 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -188,7 +188,12 @@ def nearest_targets(node, comment) # Attach the list of comments to their respective locations in the tree. def attach_comments! - Comments.new(self).attach! + if ProgramNode === value + this = self #: ParseResult[ProgramNode] + Comments.new(this).attach! + else + raise + end end end end diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 16ae553e323501..905cd1b90b63da 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -122,7 +122,6 @@ Gem::Specification.new do |spec| "src/options.c", "src/prism.c", "prism.gemspec", - "sig/manifest.yaml", "sig/prism.rbs", "sig/prism/compiler.rbs", "sig/prism/dispatcher.rbs", diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb new file mode 100644 index 00000000000000..caab9a8549cdb9 --- /dev/null +++ b/lib/prism/ripper_compat.rb @@ -0,0 +1,208 @@ +# frozen_string_literal: true + +require "ripper" + +module Prism + # Note: This integration is not finished, and therefore still has many + # inconsistencies with Ripper. If you'd like to help out, pull requests would + # be greatly appreciated! + # + # This class is meant to provide a compatibility layer between prism and + # Ripper. It functions by parsing the entire tree first and then walking it + # and executing each of the Ripper callbacks as it goes. + # + # This class is going to necessarily be slower than the native Ripper API. It + # is meant as a stopgap until developers migrate to using prism. It is also + # meant as a test harness for the prism parser. + # + # To use this class, you treat `Prism::RipperCompat` effectively as you would + # treat the `Ripper` class. + class RipperCompat < Visitor + # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that + # returns the arrays of [type, *children]. + class SexpBuilder < RipperCompat + private + + Ripper::PARSER_EVENTS.each do |event| + define_method(:"on_#{event}") do |*args| + [event, *args] + end + end + + Ripper::SCANNER_EVENTS.each do |event| + define_method(:"on_#{event}") do |value| + [:"@#{event}", value, [lineno, column]] + end + end + end + + # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that + # returns the same values as ::Ripper::SexpBuilder except with a couple of + # niceties that flatten linked lists into arrays. + class SexpBuilderPP < SexpBuilder + private + + def _dispatch_event_new # :nodoc: + [] + end + + def _dispatch_event_push(list, item) # :nodoc: + list << item + list + end + + Ripper::PARSER_EVENT_TABLE.each do |event, arity| + case event + when /_new\z/ + alias_method :"on_#{event}", :_dispatch_event_new if arity == 0 + when /_add\z/ + alias_method :"on_#{event}", :_dispatch_event_push + end + end + end + + # The source that is being parsed. + attr_reader :source + + # The current line number of the parser. + attr_reader :lineno + + # The current column number of the parser. + attr_reader :column + + # Create a new RipperCompat object with the given source. + def initialize(source) + @source = source + @result = nil + @lineno = nil + @column = nil + end + + ############################################################################ + # Public interface + ############################################################################ + + # True if the parser encountered an error during parsing. + def error? + result.failure? + end + + # Parse the source and return the result. + def parse + result.magic_comments.each do |magic_comment| + on_magic_comment(magic_comment.key, magic_comment.value) + end + + if error? + result.errors.each do |error| + on_parse_error(error.message) + end + else + result.value.accept(self) + end + end + + ############################################################################ + # Visitor methods + ############################################################################ + + # Visit a CallNode node. + def visit_call_node(node) + message = node.message + if message && message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments && node.arguments.arguments && node.arguments.arguments.length == 1 + left = visit(node.receiver) + right = visit(node.arguments.arguments.first) + + bounds(node.location) + on_binary(left, node.name, right) + else + raise NotImplementedError + end + end + + # Visit a FloatNode node. + def visit_float_node(node) + bounds(node.location) + on_float(node.slice) + end + + # Visit a ImaginaryNode node. + def visit_imaginary_node(node) + bounds(node.location) + on_imaginary(node.slice) + end + + # Visit an IntegerNode node. + def visit_integer_node(node) + bounds(node.location) + on_int(node.slice) + end + + # Visit a RationalNode node. + def visit_rational_node(node) + bounds(node.location) + on_rational(node.slice) + end + + # Visit a StatementsNode node. + def visit_statements_node(node) + bounds(node.location) + node.body.inject(on_stmts_new) do |stmts, stmt| + on_stmts_add(stmts, visit(stmt)) + end + end + + # Visit a ProgramNode node. + def visit_program_node(node) + statements = visit(node.statements) + bounds(node.location) + on_program(statements) + end + + ############################################################################ + # Entrypoints for subclasses + ############################################################################ + + # This is a convenience method that runs the SexpBuilder subclass parser. + def self.sexp_raw(source) + SexpBuilder.new(source).parse + end + + # This is a convenience method that runs the SexpBuilderPP subclass parser. + def self.sexp(source) + SexpBuilderPP.new(source).parse + end + + private + + # This method is responsible for updating lineno and column information + # to reflect the current node. + # + # This method could be drastically improved with some caching on the start + # of every line, but for now it's good enough. + def bounds(location) + @lineno = location.start_line + @column = location.start_column + end + + # Lazily initialize the parse result. + def result + @result ||= Prism.parse(source) + end + + def _dispatch0; end # :nodoc: + def _dispatch1(_); end # :nodoc: + def _dispatch2(_, _); end # :nodoc: + def _dispatch3(_, _, _); end # :nodoc: + def _dispatch4(_, _, _, _); end # :nodoc: + def _dispatch5(_, _, _, _, _); end # :nodoc: + def _dispatch7(_, _, _, _, _, _, _); end # :nodoc: + + alias_method :on_parse_error, :_dispatch1 + alias_method :on_magic_comment, :_dispatch2 + + (Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity| + alias_method :"on_#{event}", :"_dispatch#{arity}" + end + end +end diff --git a/prism/templates/lib/prism/dsl.rb.erb b/prism/templates/lib/prism/dsl.rb.erb index 7c55fb10bcd1fd..4c139ca281c4c6 100644 --- a/prism/templates/lib/prism/dsl.rb.erb +++ b/prism/templates/lib/prism/dsl.rb.erb @@ -36,6 +36,7 @@ module Prism # Create a new Location object def Location(source = nil, start_offset = 0, length = 0) + # @type var source: Source Location.new(source, start_offset, length) end <%- nodes.each do |node| -%> diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 98048989f29157..32134f8820894f 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -56,6 +56,7 @@ module Prism # Convert this node into a graphviz dot graph string. def to_dot + # @type self: node DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot end diff --git a/prism/templates/lib/prism/visitor.rb.erb b/prism/templates/lib/prism/visitor.rb.erb index 04156cc7a9dab7..4b30a1815b13ca 100644 --- a/prism/templates/lib/prism/visitor.rb.erb +++ b/prism/templates/lib/prism/visitor.rb.erb @@ -7,16 +7,19 @@ module Prism # Calls `accept` on the given node if it is not `nil`, which in turn should # call back into this visitor by calling the appropriate `visit_*` method. def visit(node) + # @type self: _Visitor node&.accept(self) end # Visits each node in `nodes` by calling `accept` on each one. def visit_all(nodes) + # @type self: _Visitor nodes.each { |node| node&.accept(self) } end # Visits the child nodes of `node` by calling `accept` on each one. def visit_child_nodes(node) + # @type self: _Visitor node.compact_child_nodes.each { |node| node.accept(self) } end end From ca8a6265862b2990a14f6a6dabc27228e9d5a995 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Mon, 8 Jan 2024 22:25:29 -0800 Subject: [PATCH 053/147] [ruby/prism] Fix my RipperCompat logic mistake from expansion for steep flow analysis https://github.com/ruby/prism/commit/f71a390c12 --- lib/prism/ripper_compat.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb index caab9a8549cdb9..51b4339426fbb9 100644 --- a/lib/prism/ripper_compat.rb +++ b/lib/prism/ripper_compat.rb @@ -109,7 +109,7 @@ def parse # Visit a CallNode node. def visit_call_node(node) message = node.message - if message && message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments && node.arguments.arguments && node.arguments.arguments.length == 1 + if message && !message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments && node.arguments.arguments && node.arguments.arguments.length == 1 left = visit(node.receiver) right = visit(node.arguments.arguments.first) From bfbaafbd9cd24cb1a7f9d653a75c883480c6078f Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Tue, 9 Jan 2024 00:39:09 -0800 Subject: [PATCH 054/147] [ruby/prism] Make rake check_annotations verify public RBS https://github.com/ruby/prism/commit/db78eef6a2 --- lib/prism.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism.rb b/lib/prism.rb index 8a2e7a61083168..b22d640b5d741d 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -44,7 +44,7 @@ module Prism # # For supported options, see Prism::parse. def self.lex_compat(source, **options) - LexCompat.new(source, **options).result + LexCompat.new(source, **options).result #: ParseResult[Array[[[Integer, Integer], Symbol, String, untyped]]] end # :call-seq: From 8fa18435234335afbf17bda88324a620e15a4323 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Tue, 9 Jan 2024 21:13:46 -0800 Subject: [PATCH 055/147] [ruby/prism] Relax Location#source to be optional https://github.com/ruby/prism/commit/9f00fe7510 --- lib/prism/parse_result.rb | 31 ++++++++++++++++------------ prism/templates/lib/prism/dsl.rb.erb | 1 - 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index c55b7b6685cf60..c00059fbfe98a4 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -168,13 +168,13 @@ def inspect # The source code that this location represents. def slice - source.slice(start_offset, length) + source!.slice(start_offset, length) end # The character offset from the beginning of the source where this location # starts. def start_character_offset - source.character_offset(start_offset) + source!.character_offset(start_offset) end # The offset from the start of the file in code units of the given encoding. @@ -190,7 +190,7 @@ def end_offset # The character offset from the beginning of the source where this location # ends. def end_character_offset - source.character_offset(end_offset) + source!.character_offset(end_offset) end # The offset from the start of the file in code units of the given encoding. @@ -200,30 +200,30 @@ def end_code_units_offset(encoding = Encoding::UTF_16LE) # The line number where this location starts. def start_line - source.line(start_offset) + source!.line(start_offset) end # The content of the line where this location starts before this location. def start_line_slice - offset = source.line_start(start_offset) - source.slice(offset, start_offset - offset) + offset = source!.line_start(start_offset) + source!.slice(offset, start_offset - offset) end # The line number where this location ends. def end_line - source.line(end_offset) + source!.line(end_offset) end # The column number in bytes where this location starts from the start of # the line. def start_column - source.column(start_offset) + source!.column(start_offset) end # The column number in characters where this location ends from the start of # the line. def start_character_column - source.character_column(start_offset) + source!.character_column(start_offset) end # The column number in code units of the given encoding where this location @@ -235,13 +235,13 @@ def start_code_units_column(encoding = Encoding::UTF_16LE) # The column number in bytes where this location ends from the start of the # line. def end_column - source.column(end_offset) + source!.column(end_offset) end # The column number in characters where this location ends from the start of # the line. def end_character_column - source.character_column(end_offset) + source!.character_column(end_offset) end # The column number in code units of the given encoding where this location @@ -281,8 +281,13 @@ def join(other) # the beginning of the file. Useful for when you want a location object but # do not care where it points. def self.null - source = nil #: Source - new(source, 0, 0) + new(nil, 0, 0) + end + + private + + def source! + source or raise "Missing source" end end diff --git a/prism/templates/lib/prism/dsl.rb.erb b/prism/templates/lib/prism/dsl.rb.erb index 4c139ca281c4c6..7c55fb10bcd1fd 100644 --- a/prism/templates/lib/prism/dsl.rb.erb +++ b/prism/templates/lib/prism/dsl.rb.erb @@ -36,7 +36,6 @@ module Prism # Create a new Location object def Location(source = nil, start_offset = 0, length = 0) - # @type var source: Source Location.new(source, start_offset, length) end <%- nodes.each do |node| -%> From 66565e36eae8a3dff53f86b3d04bf749e0b07a94 Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Tue, 9 Jan 2024 21:20:25 -0800 Subject: [PATCH 056/147] [ruby/prism] Add documentation for Location#source! https://github.com/ruby/prism/commit/467e1cc2c4 --- lib/prism/parse_result.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index c00059fbfe98a4..9771da53144de7 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -286,6 +286,7 @@ def self.null private + # Access the associated source, raising if not present. def source! source or raise "Missing source" end From dfee03374632f4da40587cf62858b92da5022a9a Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Tue, 20 Feb 2024 13:48:31 -0800 Subject: [PATCH 057/147] [ruby/prism] Replace awkward code changes with steep:ignore Also remove RBS for currently ignored files. Will follow-up when those check fully in later PRs. https://github.com/ruby/prism/commit/2cae58f86d --- lib/prism.rb | 4 ++-- lib/prism/parse_result/comments.rb | 7 +------ lib/prism/parse_result/newlines.rb | 6 +----- lib/prism/pattern.rb | 3 +-- lib/prism/prism.gemspec | 1 - lib/prism/translation.rb | 2 +- prism/templates/template.rb | 3 +-- 7 files changed, 7 insertions(+), 19 deletions(-) diff --git a/lib/prism.rb b/lib/prism.rb index b22d640b5d741d..ac746630fccc24 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -44,7 +44,7 @@ module Prism # # For supported options, see Prism::parse. def self.lex_compat(source, **options) - LexCompat.new(source, **options).result #: ParseResult[Array[[[Integer, Integer], Symbol, String, untyped]]] + LexCompat.new(source, **options).result # steep:ignore end # :call-seq: @@ -54,7 +54,7 @@ def self.lex_compat(source, **options) # returns the same tokens. Raises SyntaxError if the syntax in source is # invalid. def self.lex_ripper(source) - LexRipper.new(source).result + LexRipper.new(source).result # steep:ignore end # :call-seq: diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 4e1b9a68e572de..f8f74d25032912 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -188,12 +188,7 @@ def nearest_targets(node, comment) # Attach the list of comments to their respective locations in the tree. def attach_comments! - if ProgramNode === value - this = self #: ParseResult[ProgramNode] - Comments.new(this).attach! - else - raise - end + Comments.new(self).attach! # steep:ignore end end end diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index 96c97646ff141a..927c17fe2f7064 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -58,11 +58,7 @@ def visit_statements_node(node) # Walk the tree and mark nodes that are on a new line. def mark_newlines! - if ProgramNode === value - value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) - else - raise "ParseResult does not contain ProgramNode value" - end + value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) # steep:ignore end end end diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index 8e0d235796cd2b..57b30fe678a703 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -87,11 +87,10 @@ def scan(root) return to_enum(__method__ || raise, root) unless block_given? @compiled ||= compile - compiled = @compiled #: Proc queue = [root] while (node = queue.shift) - yield node if compiled.call(node) + yield node if @compiled.call(node) # steep:ignore queue.concat(node.compact_child_nodes) end end diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 905cd1b90b63da..58201ed53a1698 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -133,7 +133,6 @@ Gem::Specification.new do |spec| "sig/prism/pack.rbs", "sig/prism/parse_result.rbs", "sig/prism/pattern.rbs", - "sig/prism/ripper_compat.rbs", "sig/prism/serialize.rbs", "sig/prism/visitor.rbs", "rbi/prism.rbi", diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb index 84b9311fe2de31..e367c6e05321ef 100644 --- a/lib/prism/translation.rb +++ b/lib/prism/translation.rb @@ -3,7 +3,7 @@ module Prism # This module is responsible for converting the prism syntax tree into other # syntax trees. - module Translation + module Translation # steep:ignore autoload :Parser, "prism/translation/parser" autoload :Ripper, "prism/translation/ripper" autoload :RubyParser, "prism/translation/ruby_parser" diff --git a/prism/templates/template.rb b/prism/templates/template.rb index aba909bdc3b770..d981b8959265c5 100755 --- a/prism/templates/template.rb +++ b/prism/templates/template.rb @@ -588,8 +588,7 @@ def locals "sig/prism/mutation_compiler.rbs", "sig/prism/node.rbs", "sig/prism/visitor.rbs", - "sig/prism/_private/dot_visitor.rbs", - "sig/prism/_private/ripper_compat.rbs", + "sig/prism/_private/dot_visitor.rbs" ] end From aa8841405bd48ac61b3c1397dd864ed2db3b3b2a Mon Sep 17 00:00:00 2001 From: Gopal Patel Date: Thu, 22 Feb 2024 10:38:22 -0800 Subject: [PATCH 058/147] [ruby/prism] Less code modifications. More steep:ignore for now https://github.com/ruby/prism/commit/7905bdbf83 --- lib/prism/parse_result.rb | 31 +++++++++++----------------- lib/prism/pattern.rb | 5 ++--- prism/templates/lib/prism/dsl.rb.erb | 2 +- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 9771da53144de7..af4006d6831f0a 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -168,13 +168,13 @@ def inspect # The source code that this location represents. def slice - source!.slice(start_offset, length) + source.slice(start_offset, length) end # The character offset from the beginning of the source where this location # starts. def start_character_offset - source!.character_offset(start_offset) + source.character_offset(start_offset) end # The offset from the start of the file in code units of the given encoding. @@ -190,7 +190,7 @@ def end_offset # The character offset from the beginning of the source where this location # ends. def end_character_offset - source!.character_offset(end_offset) + source.character_offset(end_offset) end # The offset from the start of the file in code units of the given encoding. @@ -200,30 +200,30 @@ def end_code_units_offset(encoding = Encoding::UTF_16LE) # The line number where this location starts. def start_line - source!.line(start_offset) + source.line(start_offset) end # The content of the line where this location starts before this location. def start_line_slice - offset = source!.line_start(start_offset) - source!.slice(offset, start_offset - offset) + offset = source.line_start(start_offset) + source.slice(offset, start_offset - offset) end # The line number where this location ends. def end_line - source!.line(end_offset) + source.line(end_offset) end # The column number in bytes where this location starts from the start of # the line. def start_column - source!.column(start_offset) + source.column(start_offset) end # The column number in characters where this location ends from the start of # the line. def start_character_column - source!.character_column(start_offset) + source.character_column(start_offset) end # The column number in code units of the given encoding where this location @@ -235,13 +235,13 @@ def start_code_units_column(encoding = Encoding::UTF_16LE) # The column number in bytes where this location ends from the start of the # line. def end_column - source!.column(end_offset) + source.column(end_offset) end # The column number in characters where this location ends from the start of # the line. def end_character_column - source!.character_column(end_offset) + source.character_column(end_offset) end # The column number in code units of the given encoding where this location @@ -281,14 +281,7 @@ def join(other) # the beginning of the file. Useful for when you want a location object but # do not care where it points. def self.null - new(nil, 0, 0) - end - - private - - # Access the associated source, raising if not present. - def source! - source or raise "Missing source" + new(nil, 0, 0) # steep:ignore end end diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb index 57b30fe678a703..e12cfd597f268e 100644 --- a/lib/prism/pattern.rb +++ b/lib/prism/pattern.rb @@ -84,7 +84,7 @@ def compile # matches the pattern. If no block is given, an enumerator will be returned # that will yield each node that matches the pattern. def scan(root) - return to_enum(__method__ || raise, root) unless block_given? + return to_enum(:scan, root) unless block_given? @compiled ||= compile queue = [root] @@ -182,8 +182,7 @@ def compile_hash_pattern_node(node) preprocessed = node.elements.to_h do |element| key = element.key - if key.respond_to?(:unescaped) - # @type var key: SymbolNode + if key.is_a?(SymbolNode) [key.unescaped.to_sym, compile_node(element.value)] else raise CompilationError, element.inspect diff --git a/prism/templates/lib/prism/dsl.rb.erb b/prism/templates/lib/prism/dsl.rb.erb index 7c55fb10bcd1fd..8dbb540952d927 100644 --- a/prism/templates/lib/prism/dsl.rb.erb +++ b/prism/templates/lib/prism/dsl.rb.erb @@ -36,7 +36,7 @@ module Prism # Create a new Location object def Location(source = nil, start_offset = 0, length = 0) - Location.new(source, start_offset, length) + Location.new(source, start_offset, length) # steep:ignore end <%- nodes.each do |node| -%> From 804b2a3787e17ccc4537b4c525d4f81adc27ab7c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 23 Feb 2024 22:21:10 -0500 Subject: [PATCH 059/147] [ruby/prism] Rebase against main https://github.com/ruby/prism/commit/813e20d449 --- lib/prism/parse_result.rb | 2 +- lib/prism/ripper_compat.rb | 208 ------------------------------------- 2 files changed, 1 insertion(+), 209 deletions(-) delete mode 100644 lib/prism/ripper_compat.rb diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index af4006d6831f0a..102567f59c82d5 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -67,7 +67,7 @@ def character_column(byte_offset) # concept of code units that differs from the number of characters in other # encodings, it is not captured here. def code_units_offset(byte_offset, encoding) - byteslice = source.byteslice(0, byte_offset).encode(encoding) + byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding) (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length end diff --git a/lib/prism/ripper_compat.rb b/lib/prism/ripper_compat.rb deleted file mode 100644 index 51b4339426fbb9..00000000000000 --- a/lib/prism/ripper_compat.rb +++ /dev/null @@ -1,208 +0,0 @@ -# frozen_string_literal: true - -require "ripper" - -module Prism - # Note: This integration is not finished, and therefore still has many - # inconsistencies with Ripper. If you'd like to help out, pull requests would - # be greatly appreciated! - # - # This class is meant to provide a compatibility layer between prism and - # Ripper. It functions by parsing the entire tree first and then walking it - # and executing each of the Ripper callbacks as it goes. - # - # This class is going to necessarily be slower than the native Ripper API. It - # is meant as a stopgap until developers migrate to using prism. It is also - # meant as a test harness for the prism parser. - # - # To use this class, you treat `Prism::RipperCompat` effectively as you would - # treat the `Ripper` class. - class RipperCompat < Visitor - # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that - # returns the arrays of [type, *children]. - class SexpBuilder < RipperCompat - private - - Ripper::PARSER_EVENTS.each do |event| - define_method(:"on_#{event}") do |*args| - [event, *args] - end - end - - Ripper::SCANNER_EVENTS.each do |event| - define_method(:"on_#{event}") do |value| - [:"@#{event}", value, [lineno, column]] - end - end - end - - # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that - # returns the same values as ::Ripper::SexpBuilder except with a couple of - # niceties that flatten linked lists into arrays. - class SexpBuilderPP < SexpBuilder - private - - def _dispatch_event_new # :nodoc: - [] - end - - def _dispatch_event_push(list, item) # :nodoc: - list << item - list - end - - Ripper::PARSER_EVENT_TABLE.each do |event, arity| - case event - when /_new\z/ - alias_method :"on_#{event}", :_dispatch_event_new if arity == 0 - when /_add\z/ - alias_method :"on_#{event}", :_dispatch_event_push - end - end - end - - # The source that is being parsed. - attr_reader :source - - # The current line number of the parser. - attr_reader :lineno - - # The current column number of the parser. - attr_reader :column - - # Create a new RipperCompat object with the given source. - def initialize(source) - @source = source - @result = nil - @lineno = nil - @column = nil - end - - ############################################################################ - # Public interface - ############################################################################ - - # True if the parser encountered an error during parsing. - def error? - result.failure? - end - - # Parse the source and return the result. - def parse - result.magic_comments.each do |magic_comment| - on_magic_comment(magic_comment.key, magic_comment.value) - end - - if error? - result.errors.each do |error| - on_parse_error(error.message) - end - else - result.value.accept(self) - end - end - - ############################################################################ - # Visitor methods - ############################################################################ - - # Visit a CallNode node. - def visit_call_node(node) - message = node.message - if message && !message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments && node.arguments.arguments && node.arguments.arguments.length == 1 - left = visit(node.receiver) - right = visit(node.arguments.arguments.first) - - bounds(node.location) - on_binary(left, node.name, right) - else - raise NotImplementedError - end - end - - # Visit a FloatNode node. - def visit_float_node(node) - bounds(node.location) - on_float(node.slice) - end - - # Visit a ImaginaryNode node. - def visit_imaginary_node(node) - bounds(node.location) - on_imaginary(node.slice) - end - - # Visit an IntegerNode node. - def visit_integer_node(node) - bounds(node.location) - on_int(node.slice) - end - - # Visit a RationalNode node. - def visit_rational_node(node) - bounds(node.location) - on_rational(node.slice) - end - - # Visit a StatementsNode node. - def visit_statements_node(node) - bounds(node.location) - node.body.inject(on_stmts_new) do |stmts, stmt| - on_stmts_add(stmts, visit(stmt)) - end - end - - # Visit a ProgramNode node. - def visit_program_node(node) - statements = visit(node.statements) - bounds(node.location) - on_program(statements) - end - - ############################################################################ - # Entrypoints for subclasses - ############################################################################ - - # This is a convenience method that runs the SexpBuilder subclass parser. - def self.sexp_raw(source) - SexpBuilder.new(source).parse - end - - # This is a convenience method that runs the SexpBuilderPP subclass parser. - def self.sexp(source) - SexpBuilderPP.new(source).parse - end - - private - - # This method is responsible for updating lineno and column information - # to reflect the current node. - # - # This method could be drastically improved with some caching on the start - # of every line, but for now it's good enough. - def bounds(location) - @lineno = location.start_line - @column = location.start_column - end - - # Lazily initialize the parse result. - def result - @result ||= Prism.parse(source) - end - - def _dispatch0; end # :nodoc: - def _dispatch1(_); end # :nodoc: - def _dispatch2(_, _); end # :nodoc: - def _dispatch3(_, _, _); end # :nodoc: - def _dispatch4(_, _, _, _); end # :nodoc: - def _dispatch5(_, _, _, _, _); end # :nodoc: - def _dispatch7(_, _, _, _, _, _, _); end # :nodoc: - - alias_method :on_parse_error, :_dispatch1 - alias_method :on_magic_comment, :_dispatch2 - - (Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity| - alias_method :"on_#{event}", :"_dispatch#{arity}" - end - end -end From e9e752c7efe95e7166c7bb59277b6e3afe11851c Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 23 Feb 2024 20:18:41 -0800 Subject: [PATCH 060/147] Assert running_iseq before using it When running_iseq happens to be 0, it's better to fail on the assertion rather than referencing the null pointer. --- yjit/src/core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yjit/src/core.rs b/yjit/src/core.rs index 3843e91e2ef8aa..90e6490997497c 100644 --- a/yjit/src/core.rs +++ b/yjit/src/core.rs @@ -2749,14 +2749,14 @@ fn branch_stub_hit_body(branch_ptr: *const c_void, target_idx: u32, ec: EcPtr) - let original_interp_sp = get_cfp_sp(cfp); let running_iseq = get_cfp_iseq(cfp); + assert_eq!(running_iseq, target_blockid.iseq as _, "each stub expects a particular iseq"); + let reconned_pc = rb_iseq_pc_at_idx(running_iseq, target_blockid.idx.into()); let reconned_sp = original_interp_sp.offset(target_ctx.sp_offset.into()); // Unlike in the interpreter, our `leave` doesn't write to the caller's // SP -- we do it in the returned-to code. Account for this difference. let reconned_sp = reconned_sp.add(target_ctx.is_return_landing().into()); - assert_eq!(running_iseq, target_blockid.iseq as _, "each stub expects a particular iseq"); - // Update the PC in the current CFP, because it may be out of sync in JITted code rb_set_cfp_pc(cfp, reconned_pc); From 2c0cf6837cc22d2d240f743d54a93f4dbe5acf5c Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Sat, 24 Feb 2024 17:53:38 +0900 Subject: [PATCH 061/147] Launchable: Fix the warning of pip --- .github/workflows/macos.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index b0d03547aae196..9e720fcec04d19 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -115,7 +115,7 @@ jobs: - name: Set up Python uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 with: - python-version: "3.10" + python-version: "3.x" if: steps.enable_launchable.outputs.enable_launchable - name: Set up Java @@ -128,7 +128,9 @@ jobs: - name: Set up Launchable run: | set -x - pip install launchable + PATH=$PATH:$(python -msite --user-base)/bin + echo "PATH=$PATH" >> $GITHUB_ENV + pip install --user launchable launchable verify : # The build name cannot include a slash, so we replace the string here. github_ref="$(echo ${{ github.ref }} | sed 's/\//_/g')" From 30b99868f999f58ab856a2a3d69c8b068b9b5803 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 28 Apr 2023 21:59:57 +0900 Subject: [PATCH 062/147] [ruby/resolv] Treat hostname as same as aliases https://github.com/ruby/resolv/commit/fa812d6454 --- lib/resolv.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/resolv.rb b/lib/resolv.rb index d878d3831b9290..54e8a6feb483d2 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -194,16 +194,13 @@ def lazy_initialize # :nodoc: File.open(@filename, 'rb') {|f| f.each {|line| line.sub!(/#.*/, '') - addr, hostname, *aliases = line.split(/\s+/) + addr, *hostnames = line.split(/\s+/) next unless addr @addr2name[addr] = [] unless @addr2name.include? addr - @addr2name[addr] << hostname - @addr2name[addr].concat(aliases) - @name2addr[hostname] = [] unless @name2addr.include? hostname - @name2addr[hostname] << addr - aliases.each {|n| - @name2addr[n] = [] unless @name2addr.include? n - @name2addr[n] << addr + @addr2name[addr].concat(hostnames) + hostnames.each {|hostname| + @name2addr[hostname] = [] unless @name2addr.include? hostname + @name2addr[hostname] << addr } } } From 012a0b91252da7b3b23e679dd50a1571a59f5a21 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 13:06:04 +0900 Subject: [PATCH 063/147] [ruby/resolv] Simplify adding new entries https://github.com/ruby/resolv/commit/081b8df705 --- lib/resolv.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/resolv.rb b/lib/resolv.rb index 54e8a6feb483d2..1363d49dc45017 100644 --- a/lib/resolv.rb +++ b/lib/resolv.rb @@ -196,12 +196,8 @@ def lazy_initialize # :nodoc: line.sub!(/#.*/, '') addr, *hostnames = line.split(/\s+/) next unless addr - @addr2name[addr] = [] unless @addr2name.include? addr - @addr2name[addr].concat(hostnames) - hostnames.each {|hostname| - @name2addr[hostname] = [] unless @name2addr.include? hostname - @name2addr[hostname] << addr - } + (@addr2name[addr] ||= []).concat(hostnames) + hostnames.each {|hostname| (@name2addr[hostname] ||= []) << addr} } } @name2addr.each {|name, arr| arr.reverse!} From 7356067b73f9f1a4c8a06546611ec242af1fa192 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 14:03:51 +0900 Subject: [PATCH 064/147] [ruby/tmpdir] Update gemspec according to the recent bundler template https://github.com/ruby/tmpdir/commit/4ef7bc4f2a --- lib/tmpdir.gemspec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec index a7463105fa45c6..15fbd1d4c883fe 100644 --- a/lib/tmpdir.gemspec +++ b/lib/tmpdir.gemspec @@ -15,8 +15,11 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + spec.files = Dir.chdir(__dir__) do + `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject do |f| + (File.expand_path(f) == __FILE__) || + f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) + end end spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } From 2721a64e4192fee250442cd6157c5a85908a20d4 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 25 Feb 2024 15:08:27 +0800 Subject: [PATCH 065/147] [ruby/reline] Use gray and white as the default dialog theme (https://github.com/ruby/reline/pull/637) I think this has a few benefits: 1. Most terminal themes generally don't change or pick similar colors for their black and white colors, so it's more likely to be consistent across terminals/themes. 2. They don't have the potential color-blind issues that other color options may have. 3. We won't need additional changes for no color mode. https://github.com/ruby/reline/commit/6579a0a737 --- lib/reline/face.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/reline/face.rb b/lib/reline/face.rb index e18ec957e8a49f..d07196e2e7ce3c 100644 --- a/lib/reline/face.rb +++ b/lib/reline/face.rb @@ -186,9 +186,9 @@ def self.load_initial_configs conf.define :scrollbar, style: :reset end config(:completion_dialog) do |conf| - conf.define :default, foreground: :white, background: :cyan - conf.define :enhanced, foreground: :white, background: :magenta - conf.define :scrollbar, foreground: :white, background: :cyan + conf.define :default, foreground: :bright_white, background: :gray + conf.define :enhanced, foreground: :black, background: :white + conf.define :scrollbar, foreground: :white, background: :gray end end From 2c1b7bc51c335d85da994c87dfb37c0e3c894eb9 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 25 Feb 2024 16:07:03 +0800 Subject: [PATCH 066/147] [ruby/reline] Bump version to v0.4.3 (https://github.com/ruby/reline/pull/642) https://github.com/ruby/reline/commit/5137a3f3af --- lib/reline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reline/version.rb b/lib/reline/version.rb index 0ed38259083a35..4ddc186ebb7062 100644 --- a/lib/reline/version.rb +++ b/lib/reline/version.rb @@ -1,3 +1,3 @@ module Reline - VERSION = '0.4.2' + VERSION = '0.4.3' end From 6108962030576ce8e5501c6b7f4e7450a5375a0a Mon Sep 17 00:00:00 2001 From: git Date: Sun, 25 Feb 2024 08:07:53 +0000 Subject: [PATCH 067/147] Update default gems list at 2c1b7bc51c335d85da994c87dfb37c [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 2c3d79f548430d..9c402df783f613 100644 --- a/NEWS.md +++ b/NEWS.md @@ -30,7 +30,7 @@ The following default gems are updated. * irb 1.11.2 * net-http 0.4.1 * prism 0.24.0 -* reline 0.4.2 +* reline 0.4.3 * stringio 3.1.1 * strscan 3.1.1 From c0c56d1714b44d30d69b51127f9c97df21322d58 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 17:14:52 +0900 Subject: [PATCH 068/147] [ruby/tmpdir] Use `IO.popen` to list files - Redirect `git ls-files` without shelling out. - When building by `gem`, `__FILE__` is the path name given in the command line, or the gemspec file name in the current directory. In that case, comparison it and expanded path never equal. Compare listed file names with the base name of `__FILE__` instead. https://github.com/ruby/tmpdir/commit/f505e3f7cb --- lib/tmpdir.gemspec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec index 15fbd1d4c883fe..d4bb892cc6a5fd 100644 --- a/lib/tmpdir.gemspec +++ b/lib/tmpdir.gemspec @@ -15,9 +15,10 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(__dir__) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject do |f| - (File.expand_path(f) == __FILE__) || + gemspec = File.basename(__FILE__) + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| + ls.readlines("\x0", chomp: true).reject do |f| + (f == gemspec) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) end end From c16b507563b72b33277e9b9745cb1e41e1bcf93f Mon Sep 17 00:00:00 2001 From: Adam Daniels Date: Sun, 25 Feb 2024 03:36:37 -0500 Subject: [PATCH 069/147] [ruby/tmpdir] [DOC] `require` inside each method on Dir (https://github.com/ruby/tmpdir/pull/31) https://github.com/ruby/tmpdir/commit/a1ec977923 --- lib/tmpdir.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb index 70bd010de55a90..65c86e9b90e4ef 100644 --- a/lib/tmpdir.rb +++ b/lib/tmpdir.rb @@ -22,6 +22,9 @@ class Dir ## # Returns the operating system's temporary file path. + # + # require 'tmpdir' + # Dir.tmpdir # => "/tmp" def self.tmpdir ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', SYSTMPDIR], ['/tmp']*2, ['.']*2].find do |name, dir| @@ -45,6 +48,11 @@ def self.tmpdir # Dir.mktmpdir creates a temporary directory. # + # require 'tmpdir' + # Dir.mktmpdir {|dir| + # # use the directory + # } + # # The directory is created with 0700 permission. # Application should not change the permission to make the temporary directory accessible from other users. # From eb661364afbeabf6a1d0ab30b01efebb826ff6bf Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 7 Feb 2024 00:42:08 +0900 Subject: [PATCH 070/147] Add `.mailmap` file to map SVN IDs [ci skip] --- .mailmap | 431 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000000000..36bef53d644de6 --- /dev/null +++ b/.mailmap @@ -0,0 +1,431 @@ +git[bot] +git[bot] git +svn[bot] svn + +# a_matsuda +Akira Matsuda (a_matsuda) +Akira Matsuda (a_matsuda) + +# aamine +Minero Aoki (aamine) +Minero Aoki (aamine) + +# akira +akira yamada (akira) +## akira yamada (akira) +akira yamada (akira) +akira yamada (akira) + +# akiyoshi +AKIYOSHI, Masamichi (akiyoshi) +AKIYOSHI, Masamichi (akiyoshi) + +# akr +Tanaka Akira (akr) +Tanaka Akira (akr) + +# arai +Koji Arai (arai) +Koji Arai (arai) + +# arton +Akio Tajima (arton) +Akio Tajima (arton) + +# aycabta +aycabta (aycabta) +aycabta (aycabta) + +# ayumin +Ayumu AIZAWA (ayumin) +Ayumu AIZAWA (ayumin) + +# azav +Alexander Zavorine (azav) +Alexander Zavorine (azav) + +# charliesome +Charlie Somerville (charliesome) +Charlie Somerville (charliesome) + +# dave +Dave Thomas (dave) +Dave Thomas (dave) + +# davidflanagan +David Flanagan (davidflanagan) +David Flanagan (davidflanagan) +David Flanagan (davidflanagan) +David Flanagan (davidflanagan) + +# dblack +David A. Black (dblack) +David A. Black (dblack) +David A. Black (dblack) +David A. Black (dblack) + +# drbrain +Eric Hodel (drbrain) +Eric Hodel (drbrain) + +# duerst +Martin Dürst (duerst) +Martin Dürst (duerst) + +# eban +WATANABE Hirofumi (eban) +WATANABE Hirofumi (eban) + +# emboss +Martin Bosslet (emboss) +Martin Bosslet (emboss) +Martin Bosslet (emboss) + +# eregon +Benoit Daloze (eregon) +Benoit Daloze (eregon) + +# evan +Evan Phoenix (evan) +Evan Phoenix (evan) +Evan Phoenix (evan) + +# glass +Masaki Matsushita (glass) +Masaki Matsushita (glass) + +# gogotanaka +Kazuki Tanaka (gogotanaka) +Kazuki Tanaka (gogotanaka) + +# gotoken +Kentaro Goto (gotoken) +Kentaro Goto (gotoken) + +# gotoyuzo +GOTOU Yuuzou (gotoyuzo) +GOTOU Yuuzou (gotoyuzo) + +# gsinclair +Gavin Sinclair (gsinclair) +Gavin Sinclair (gsinclair) + +# H_Konishi +KONISHI Hiromasa (H_Konishi) +KONISHI Hiromasa (H_Konishi) + +# headius +Charles Oliver Nutter (headius) +Charles Oliver Nutter (headius) + +# hone +Terence Lee (hone) +Terence Lee (hone) + +# hsbt +Hiroshi SHIBATA (hsbt) +Hiroshi SHIBATA (hsbt) + +# iwamatsu +Nobuhiro Iwamatsu (iwamatsu) +Nobuhiro Iwamatsu (iwamatsu) + +# jeg2 +James Edward Gray II (jeg2) +James Edward Gray II (jeg2) + +# jim +Jim Weirich (jim) +Jim Weirich (jim) + +# k0kubun +Takashi Kokubun (k0kubun) +Takashi Kokubun (k0kubun) + +# kanemoto +Yutaka Kanemoto (kanemoto) +Yutaka Kanemoto (kanemoto) + +# katsu +UENO Katsuhiro (katsu) +UENO Katsuhiro (katsu) + +# kazu +Kazuhiro NISHIYAMA (kazu) +Kazuhiro NISHIYAMA (kazu) + +# keiju +Keiju Ishitsuka (keiju) +Keiju Ishitsuka (keiju) + +# knu +Akinori MUSHA (knu) +Akinori MUSHA (knu) + +# ko1 +Koichi Sasada (ko1) +Koichi Sasada (ko1) + +# kosaki +KOSAKI Motohiro (kosaki) +KOSAKI Motohiro (kosaki) + +# kosako +K.Kosako (kosako) +K.Kosako (kosako) + +# kou +Sutou Kouhei (kou) +Sutou Kouhei (kou) +Sutou Kouhei (kou) + +# kouji +Kouji Takao (kouji) +Kouji Takao (kouji) +Kouji Takao (kouji) + +# ksaito +Kazuo Saito (ksaito) +Kazuo Saito (ksaito) + +# ktsj +Kazuki Tsujimoto (ktsj) +Kazuki Tsujimoto (ktsj) + +# luislavena +Luis Lavena (luislavena) +Luis Lavena (luislavena) + +# mame +Yusuke Endoh (mame) +## Yusuke Endoh (mame) +Yusuke Endoh (mame) + +# marcandre +Marc-Andre Lafortune (marcandre) +Marc-Andre Lafortune (marcandre) +Marc-Andre Lafortune (marcandre) + +# matz +Yukihiro "Matz" Matsumoto (matz) +Yukihiro "Matz" Matsumoto (matz) +Yukihiro "Matz" Matsumoto (matz) + +# michal +Michal Rokos (michal) +Michal Rokos (michal) + +# mneumann +Michael Neumann (mneumann) +Michael Neumann (mneumann) + +# mrkn +Kenta Murata (mrkn) +Kenta Murata (mrkn) +Kenta Murata (mrkn) <3959+mrkn@users.noreply.github.com> +Kenta Murata (mrkn) + +# nagachika +nagachika (nagachika) +nagachika (nagachika) + +# nagai +Hidetoshi NAGAI (nagai) +Hidetoshi NAGAI (nagai) + +# nahi +Hiroshi Nakamura (nahi) +Hiroshi Nakamura (nahi) + +# nari +Narihiro Nakamura (nari) +Narihiro Nakamura (nari) + +# naruse +NARUSE, Yui (naruse) +NARUSE, Yui (naruse) +NARUSE, Yui (naruse) + +# ngoto +Naohisa Goto (ngoto) +Naohisa Goto (ngoto) + +# nobu +Nobuyoshi Nakada (nobu) +Nobuyoshi Nakada (nobu) + +# normal +Eric Wong (normal) +Eric Wong (normal) +Eric Wong (normal) + +# ntalbott +Nathaniel Talbott (ntalbott) +Nathaniel Talbott (ntalbott) + +# ocean +Hirokazu Yamamoto (ocean) +Hirokazu Yamamoto (ocean) + +# odaira +Rei Odaira (odaira) +Rei Odaira (odaira) +Rei Odaira (odaira) + +# okkez +okkez (okkez) +okkez (okkez) + +# rhe +Kazuki Yamaguchi (rhe) +Kazuki Yamaguchi (rhe) + +# ryan +Ryan Davis (ryan) +Ryan Davis (ryan) +Ryan Davis (ryan) + +# samuel +Samuel Williams (samuel) +Samuel Williams (samuel) + +# seki +Masatoshi SEKI (seki) +Masatoshi SEKI (seki) + +# ser +Sean Russell (ser) +Sean Russell (ser) + +# shigek +Shigeo Kobayashi (shigek) +Shigeo Kobayashi (shigek) + +# shirosaki +Hiroshi Shirosaki (shirosaki) +Hiroshi Shirosaki (shirosaki) + +# sho-h +Sho Hashimoto (sho-h) +Sho Hashimoto (sho-h) +Sho Hashimoto (sho-h) +Sho Hashimoto (sho-h) + +# shugo +Shugo Maeda (shugo) +Shugo Maeda (shugo) + +# shyouhei +卜部昌平 (shyouhei) +卜部昌平 (shyouhei) + +# siena +Siena. (siena) +Siena. (siena) + +# sonots +sonots (sonots) +sonots (sonots) + +# sorah +Sorah Fukumori (sorah) +Sorah Fukumori (sorah) + +# stomar +Marcus Stollsteimer (stomar) +Marcus Stollsteimer (stomar) + +# suke +Masaki Suketa (suke) +Masaki Suketa (suke) + +# tadd +Tadashi Saito (tadd) +Tadashi Saito (tadd) + +# tadf +Tadayoshi Funaba (tadf) +Tadayoshi Funaba (tadf) + +# takano32 +TAKANO Mitsuhiro (takano32) +TAKANO Mitsuhiro (takano32) + +# tarui +Masaya Tarui (tarui) +Masaya Tarui (tarui) + +# technorama +Technorama Ltd. (technorama) +Technorama Ltd. (technorama) + +# tenderlove +Aaron Patterson (tenderlove) +Aaron Patterson (tenderlove) + +# tmm1 +Aman Gupta (tmm1) +Aman Gupta (tmm1) + +# ts +Guy Decoux (ts) +Guy Decoux (ts) + +# ttate +Takaaki Tateishi (ttate) +## Takaaki Tateishi (ttate) +Takaaki Tateishi (ttate) + +# uema2 +Takaaki Uematsu (uema2) +Takaaki Uematsu (uema2) + +# usa +U.Nakamura (usa) +U.Nakamura (usa) +U.Nakamura (usa) + +# wakou +Wakou Aoyama (wakou) +Wakou Aoyama (wakou) + +# wanabe +wanabe (wanabe) +wanabe (wanabe) + +# watson1978 +Watson (watson1978) +Watson (watson1978) + +# wew +William Webber (wew) +William Webber (wew) + +# why +why the lucky stiff (why) +why the lucky stiff (why) + +# xibbar +Takeyuki FUJIOKA (xibbar) +Takeyuki FUJIOKA (xibbar) + +# yugui +Yuki Yugui Sonoda (yugui) +Yuki Yugui Sonoda (yugui) + +# yui-knk +yui-knk (yui-knk) +yui-knk (yui-knk) + +# yuki +Yuki Nishijima (yuki) +Yuki Nishijima (yuki) +Yuki Nishijima (yuki) + +# zsombor +Dee Zsombor (zsombor) +Dee Zsombor (zsombor) + +# zzak +zzak (zzak) +zzak (zzak) From 3c4d0b13132f9ba3f07575f175d173b69f9bd6ef Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 19:12:55 +0900 Subject: [PATCH 071/147] Exclude `.mailmap` from snapshots [ci skip] It is only for old commits, useless without full repository logs. --- tool/lib/vcs.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/lib/vcs.rb b/tool/lib/vcs.rb index 900ea59017b67c..3894f9c8e8d5c1 100644 --- a/tool/lib/vcs.rb +++ b/tool/lib/vcs.rb @@ -226,6 +226,7 @@ def relative_to(path) def after_export(dir) FileUtils.rm_rf(Dir.glob("#{dir}/.git*")) + FileUtils.rm_rf(Dir.glob("#{dir}/.mailmap")) end def revision_handler(rev) From 898f30f8bd064c9803625c98a3e46bd3434ff1bb Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 25 Feb 2024 23:20:56 +0800 Subject: [PATCH 072/147] [ruby/irb] Refactor IRB::Context#prompting (https://github.com/ruby/irb/pull/889) https://github.com/ruby/irb/commit/7b323ee514 --- lib/irb/context.rb | 4 +--- lib/irb/input-method.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/irb/context.rb b/lib/irb/context.rb index d2d0bed522c6db..9647327037cb19 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -479,9 +479,7 @@ def verbose? # StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io # for more information. def prompting? - verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) || - @io.kind_of?(RelineInputMethod) || - (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod))) + verbose? || @io.prompting? end # The return value of the last statement evaluated. diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index a483ec671b044f..c1998309283fc3 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -44,6 +44,10 @@ def support_history_saving? false end + def prompting? + false + end + # For debug message def inspect 'Abstract InputMethod' @@ -91,6 +95,10 @@ def readable_after_eof? true end + def prompting? + STDIN.tty? + end + # Returns the current line number for #io. # # #line counts the number of times #gets is called. @@ -220,6 +228,10 @@ def eof? @eof end + def prompting? + true + end + # For debug message def inspect readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline' @@ -467,6 +479,10 @@ def eof? @eof end + def prompting? + true + end + # For debug message def inspect config = Reline::Config.new From c976cb52a2594e9eb147df126617d430766c9d18 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Sun, 25 Feb 2024 23:22:30 +0800 Subject: [PATCH 073/147] [ruby/irb] Add help messages to `show_source` and `show_doc` commands (https://github.com/ruby/irb/pull/887) * Add help message to the show_source command * Add help message to the show_doc command https://github.com/ruby/irb/commit/06f43aadb3 --- lib/irb/command/show_doc.rb | 16 +++++++++++++++- lib/irb/command/show_source.rb | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/irb/command/show_doc.rb b/lib/irb/command/show_doc.rb index dca10ec4be50a7..4dde28bee9bbaf 100644 --- a/lib/irb/command/show_doc.rb +++ b/lib/irb/command/show_doc.rb @@ -15,7 +15,21 @@ def transform_args(args) end category "Context" - description "Enter the mode to look up RI documents." + description "Look up documentation with RI." + + help_message <<~HELP_MESSAGE + Usage: show_doc [name] + + When name is provided, IRB will look up the documentation for the given name. + When no name is provided, a RI session will be started. + + Examples: + + show_doc + show_doc Array + show_doc Array#each + + HELP_MESSAGE def execute(*names) require 'rdoc/ri/driver' diff --git a/lib/irb/command/show_source.rb b/lib/irb/command/show_source.rb index cc783e75321e64..32bdf74d313e92 100644 --- a/lib/irb/command/show_source.rb +++ b/lib/irb/command/show_source.rb @@ -8,7 +8,21 @@ module IRB module Command class ShowSource < Base category "Context" - description "Show the source code of a given method or constant." + description "Show the source code of a given method, class/module, or constant." + + help_message <<~HELP_MESSAGE + Usage: show_source [target] [-s] + + -s Show the super method. You can stack it like `-ss` to show the super of the super, etc. + + Examples: + + show_source Foo + show_source Foo#bar + show_source Foo#bar -s + show_source Foo.baz + show_source Foo::BAR + HELP_MESSAGE class << self def transform_args(args) From a1ca96e1fdf4e234124bcff91d822584a6997833 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 02:10:36 +0000 Subject: [PATCH 074/147] Bump github/codeql-action from 3.24.4 to 3.24.5 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.4 to 3.24.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e2e140ad1441662206e8f97754b166877dfa1c73...47b3d888fe66b639e431abf22ebca059152f1eea) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/scorecards.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 054d7abee2b039..bebc1935c4bd84 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -78,15 +78,15 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 + uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 + uses: github/codeql-action/autobuild@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 + uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: category: '/language:${{ matrix.language }}' upload: False @@ -116,7 +116,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@e2e140ad1441662206e8f97754b166877dfa1c73 # v3.24.4 + uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index d409905875424c..1b631526ebe883 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@e2e140ad1441662206e8f97754b166877dfa1c73 # v2.1.27 + uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v2.1.27 with: sarif_file: results.sarif From dc146babf47a84bbd1f176d766637d4a40327019 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 26 Feb 2024 10:48:54 +0900 Subject: [PATCH 075/147] [Bug #20296] Clear errinfo when `exception: false` --- complex.c | 7 +++++-- test/ruby/test_complex.rb | 37 ++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/complex.c b/complex.c index 28d5b2058b74be..8c32c605235257 100644 --- a/complex.c +++ b/complex.c @@ -2323,8 +2323,11 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise) return a1; /* should raise exception for consistency */ if (!k_numeric_p(a1)) { - if (!raise) - return rb_protect(to_complex, a1, NULL); + if (!raise) { + a1 = rb_protect(to_complex, a1, NULL); + rb_set_errinfo(Qnil); + return a1; + } return to_complex(a1); } } diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index 5cd17d9205683b..f2a0f5b5ee2de2 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -981,30 +981,16 @@ def test_Complex_with_invalid_exception end def test_Complex_without_exception - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex('5x', exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(nil, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(Object.new, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, nil, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, Object.new, exception: false)) - } + assert_complex_without_exception('5x') + assert_complex_without_exception(nil) + assert_complex_without_exception(Object.new) + assert_complex_without_exception(1, nil) + assert_complex_without_exception(1, Object.new) o = Object.new def o.to_c; raise; end - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(o, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, o, exception: false)) - } + assert_complex_without_exception(o) + assert_complex_without_exception(1, o) end def test_respond @@ -1263,4 +1249,13 @@ def real? Complex.polar(1, obj) end end + + private + + def assert_complex_without_exception(*args) + assert_nothing_raised(ArgumentError) do + assert_nil(Complex(*args, exception: false)) + assert_nil($!) + end + end end From f23d5028059078a346efc977287b669d494a5a3f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 26 Feb 2024 11:30:11 +0900 Subject: [PATCH 076/147] [Bug #20296] Refine the test --- test/ruby/test_complex.rb | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index f2a0f5b5ee2de2..3a9bad1416fcc1 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -980,17 +980,27 @@ def test_Complex_with_invalid_exception } end - def test_Complex_without_exception - assert_complex_without_exception('5x') - assert_complex_without_exception(nil) - assert_complex_without_exception(Object.new) - assert_complex_without_exception(1, nil) - assert_complex_without_exception(1, Object.new) + def assert_complex_with_exception(error, *args, message: nil) + assert_raise(error, message) do + Complex(*args, exception: true) + end + assert_nothing_raised(error, message) do + assert_nil(Complex(*args, exception: false)) + assert_nil($!) + end + end + + def test_Complex_with_exception + assert_complex_with_exception(ArgumentError, '5x') + assert_complex_with_exception(TypeError, nil) + assert_complex_with_exception(TypeError, Object.new) + assert_complex_with_exception(TypeError, 1, nil) + assert_complex_with_exception(TypeError, 1, Object.new) o = Object.new def o.to_c; raise; end - assert_complex_without_exception(o) - assert_complex_without_exception(1, o) + assert_complex_with_exception(RuntimeError, o) + assert_complex_with_exception(TypeError, 1, o) end def test_respond @@ -1249,13 +1259,4 @@ def real? Complex.polar(1, obj) end end - - private - - def assert_complex_without_exception(*args) - assert_nothing_raised(ArgumentError) do - assert_nil(Complex(*args, exception: false)) - assert_nil($!) - end - end end From 616b414621025f50ac070b5892264f702fa4e083 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:02:00 -0800 Subject: [PATCH 077/147] Bump capstone from 0.11.0 to 0.12.0 in /yjit (#10094) Bumps [capstone](https://github.com/capstone-rust/capstone-rs) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/capstone-rust/capstone-rs/releases) - [Changelog](https://github.com/capstone-rust/capstone-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/capstone-rust/capstone-rs/compare/capstone-v0.11.0...capstone-v0.12.0) --- updated-dependencies: - dependency-name: capstone dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yjit/Cargo.lock | 8 ++++---- yjit/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yjit/Cargo.lock b/yjit/Cargo.lock index efcac306768278..5245a61aff50e1 100644 --- a/yjit/Cargo.lock +++ b/yjit/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "capstone" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1097e608594dad3bad608295567f757742b883606fe150faf7a9740b849730d8" +checksum = "b08ca438d9585a2b216b0c2e88ea51e096286c5f197f7be2526bb515ef775b6c" dependencies = [ "capstone-sys", "libc", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "capstone-sys" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7f651d5ec4c2a2e6c508f2c8032655003cd728ec85663e9796616990e25b5a" +checksum = "fe7183271711ffb7c63a6480e4baf480e0140da59eeba9b18fcc8bf3478950e3" dependencies = [ "cc", "libc", diff --git a/yjit/Cargo.toml b/yjit/Cargo.toml index f1a80b9c8ca518..0b2e286cc9c186 100644 --- a/yjit/Cargo.toml +++ b/yjit/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["staticlib"] [dependencies] # No required dependencies to simplify build process. TODO: Link to yet to be # written rationale. Optional For development and testing purposes -capstone = { version = "0.11.0", optional = true } +capstone = { version = "0.12.0", optional = true } [features] # NOTE: Development builds select a set of these via configure.ac From 9ec342e07df6aa5e2c2e9003517753a2f1b508fd Mon Sep 17 00:00:00 2001 From: Misaki Shioi <31817032+shioimm@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:14:11 +0900 Subject: [PATCH 078/147] Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp (#9374) * Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp This is an implementation of Happy Eyeballs version 2 (RFC 8305) in Socket.tcp. [Background] Currently, `Socket.tcp` synchronously resolves names and makes connection attempts with `Addrinfo::foreach.` This implementation has the following two problems. 1. In name resolution, the program stops until the DNS server responds to all DNS queries. 2. In a connection attempt, while an IP address is trying to connect to the destination host and is taking time, the program stops, and other resolved IP addresses cannot try to connect. [Proposal] "Happy Eyeballs" ([RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305)) is an algorithm to solve this kind of problem. It avoids delays to the user whenever possible and also uses IPv6 preferentially. I implemented it into `Socket.tcp` by using `Addrinfo.getaddrinfo` in each thread spawned per address family to resolve the hostname asynchronously, and using `Socket::connect_nonblock` to try to connect with multiple addrinfo in parallel. [Outcome] This change eliminates a fatal defect in the following cases. Case 1. One of the A or AAAA DNS queries does not return --- require 'socket' class Addrinfo class << self # Current Socket.tcp depends on foreach def foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block) getaddrinfo(nodename, service, Socket::AF_INET6, socktype, protocol, flags, timeout: timeout) .concat(getaddrinfo(nodename, service, Socket::AF_INET, socktype, protocol, flags, timeout: timeout)) .each(&block) end def getaddrinfo(_, _, family, *_) case family when Socket::AF_INET6 then sleep when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", 4567)] end end end end Socket.tcp("localhost", 4567) --- Because the current `Socket.tcp` cannot resolve IPv6 names, the program stops in this case. It cannot start to connect with IPv4 address. Though `Socket.tcp` with HEv2 can promptly start a connection attempt with IPv4 address in this case. Case 2. Server does not promptly return ack for syn of either IPv4 / IPv6 address family --- require 'socket' fork do socket = Socket.new(Socket::AF_INET6, :STREAM) socket.setsockopt(:SOCKET, :REUSEADDR, true) socket.bind(Socket.pack_sockaddr_in(4567, '::1')) sleep socket.listen(1) connection, _ = socket.accept connection.close socket.close end fork do socket = Socket.new(Socket::AF_INET, :STREAM) socket.setsockopt(:SOCKET, :REUSEADDR, true) socket.bind(Socket.pack_sockaddr_in(4567, '127.0.0.1')) socket.listen(1) connection, _ = socket.accept connection.close socket.close end Socket.tcp("localhost", 4567) --- The current `Socket.tcp` tries to connect serially, so when its first name resolves an IPv6 address and initiates a connection to an IPv6 server, this server does not return an ACK, and the program stops. Though `Socket.tcp` with HEv2 starts to connect sequentially and in parallel so a connection can be established promptly at the socket that attempted to connect to the IPv4 server. In exchange, the performance of `Socket.tcp` with HEv2 will be degraded. --- 100.times { Socket.tcp("www.ruby-lang.org", 80) } --- This is due to the addition of the creation of IO objects, Thread objects, etc., and calls to `IO::select` in the implementation. * Avoid NameError of Socket::EAI_ADDRFAMILY in MinGW * Support Windows with SO_CONNECT_TIME * Improve performance I have additionally implemented the following patterns: - If the host is single-stack, name resolution is performed in the main thread. This reduces the cost of creating threads. - If an IP address is specified, name resolution is performed in the main thread. This also reduces the cost of creating threads. - If only one IP address is resolved, connect is executed in blocking mode. This reduces the cost of calling IO::select. Also, I have added a fast_fallback option for users who wish not to use HE. Here are the results of each performance test. ```ruby require 'socket' require 'benchmark' HOSTNAME = "www.ruby-lang.org" PORT = 80 ai = Addrinfo.tcp(HOSTNAME, PORT) Benchmark.bmbm do |x| x.report("Domain name") do 30.times { Socket.tcp(HOSTNAME, PORT).close } end x.report("IP Address") do 30.times { Socket.tcp(ai.ip_address, PORT).close } end x.report("fast_fallback: false") do 30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close } end end ``` ``` user system total real Domain name 0.015567 0.032511 0.048078 ( 0.325284) IP Address 0.004458 0.014219 0.018677 ( 0.284361) fast_fallback: false 0.005869 0.021511 0.027380 ( 0.321891) ```` And this is the measurement result when executed in a single stack environment. ``` user system total real Domain name 0.007062 0.019276 0.026338 ( 1.905775) IP Address 0.004527 0.012176 0.016703 ( 3.051192) fast_fallback: false 0.005546 0.019426 0.024972 ( 1.775798) ``` The following is the result of the run on Ruby 3.3.0. (on Dual stack environment) ``` user system total real Ruby 3.3.0 0.007271 0.027410 0.034681 ( 0.472510) ``` (on Single stack environment) ``` user system total real Ruby 3.3.0 0.005353 0.018898 0.024251 ( 1.774535) ``` * Do not cache `Socket.ip_address_list` As mentioned in the comment at https://github.com/ruby/ruby/pull/9374#discussion_r1482269186, caching Socket.ip_address_list does not follow changes in network configuration. But if we stop caching, it becomes necessary to check every time `Socket.tcp` is called whether it's a single stack or not, which could further degrade performance in the case of a dual stack. From this, I've changed the approach so that when a domain name is passed, it doesn't check whether it's a single stack or not and resolves names in parallel each time. The performance measurement results are as follows. require 'socket' require 'benchmark' HOSTNAME = "www.ruby-lang.org" PORT = 80 ai = Addrinfo.tcp(HOSTNAME, PORT) Benchmark.bmbm do |x| x.report("Domain name") do 30.times { Socket.tcp(HOSTNAME, PORT).close } end x.report("IP Address") do 30.times { Socket.tcp(ai.ip_address, PORT).close } end x.report("fast_fallback: false") do 30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close } end end user system total real Domain name 0.004085 0.011873 0.015958 ( 0.330097) IP Address 0.000993 0.004400 0.005393 ( 0.257286) fast_fallback: false 0.001348 0.008266 0.009614 ( 0.298626) * Wait forever if fallback addresses are unresolved, unless resolv_timeout Changed from waiting only 3 seconds for name resolution when there is no fallback address available, to waiting as long as there is no resolv_timeout. This is in accordance with the current `Socket.tcp` specification. * Use exact pattern to match IPv6 address format for specify address family --- ext/socket/lib/socket.rb | 512 ++++++++++++++++++++++++++++++++++++- ext/socket/mkconstants.rb | 1 + ext/socket/rubysocket.h | 1 + include/ruby/win32.h | 1 + test/socket/test_socket.rb | 239 +++++++++++++++++ 5 files changed, 752 insertions(+), 2 deletions(-) diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index de542223c64399..e953077fe6bbde 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -599,6 +599,30 @@ def accept_nonblock(exception: true) __accept_nonblock(exception) end + RESOLUTION_DELAY = 0.05 + private_constant :RESOLUTION_DELAY + + CONNECTION_ATTEMPT_DELAY = 0.25 + private_constant :CONNECTION_ATTEMPT_DELAY + + ADDRESS_FAMILIES = { + ipv6: Socket::AF_INET6, + ipv4: Socket::AF_INET + }.freeze + private_constant :ADDRESS_FAMILIES + + HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0 + private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED + + IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/ + private_constant :IPV6_ADRESS_FORMAT + + @tcp_fast_fallback = true + + class << self + attr_accessor :tcp_fast_fallback + end + # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) @@ -624,8 +648,491 @@ def accept_nonblock(exception: true) # sock.close_write # puts sock.read # } - # - def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil) # :yield: socket + def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket + unless fast_fallback + return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) + end + + # Happy Eyeballs' states + # - :start + # - :v6c + # - :v4w + # - :v4c + # - :v46c + # - :v46w + # - :success + # - :failure + # - :timeout + + specified_family_name = nil + hostname_resolution_threads = [] + hostname_resolution_queue = nil + hostname_resolution_waiting = nil + hostname_resolution_expires_at = nil + selectable_addrinfos = SelectableAddrinfos.new + connecting_sockets = ConnectingSockets.new + local_addrinfos = [] + connection_attempt_delay_expires_at = nil + connection_attempt_started_at = nil + state = :start + connected_socket = nil + last_error = nil + is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) + + ret = loop do + case state + when :start + specified_family_name, next_state = host && specified_family_name_and_next_state(host) + + if local_host && local_port + specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name + local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + end + + if specified_family_name + addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + selectable_addrinfos.add(specified_family_name, addrinfos) + hostname_resolution_queue = NoHostnameResolutionQueue.new + state = next_state + next + end + + resolving_family_names = ADDRESS_FAMILIES.keys + hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size) + hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe + hostname_resolution_started_at = current_clocktime if resolv_timeout + hostname_resolution_args = [host, port, hostname_resolution_queue] + + hostname_resolution_threads.concat( + resolving_family_names.map { |family| + thread_args = [family, *hostname_resolution_args] + thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) } + Thread.pass + thread + } + ) + + hostname_resolution_retry_count = resolving_family_names.size - 1 + hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout + + while hostname_resolution_retry_count >= 0 + remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil + hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining) + + unless hostname_resolved + state = :timeout + break + end + + family_name, res = hostname_resolution_queue.get + + if res.is_a? Exception + unless (Socket.const_defined?(:EAI_ADDRFAMILY)) && + (res.is_a?(Socket::ResolutionError)) && + (res.error_code == Socket::EAI_ADDRFAMILY) + last_error = res + end + + if hostname_resolution_retry_count.zero? + state = :failure + break + end + hostname_resolution_retry_count -= 1 + else + state = case family_name + when :ipv6 then :v6c + when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w + end + selectable_addrinfos.add(family_name, res) + last_error = nil + break + end + end + + next + when :v4w + ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY) + + if ipv6_resolved + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + state = :v46c + else + state = :v4c + end + + next + when :v4c, :v6c, :v46c + connection_attempt_started_at = current_clocktime unless connection_attempt_started_at + addrinfo = selectable_addrinfos.get + + if local_addrinfos.any? + local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily } + + if local_addrinfo.nil? + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + last_error = SocketError.new 'no appropriate local address' + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + next + end + end + + connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY + + begin + result = if specified_family_name && selectable_addrinfos.empty? && + connecting_sockets.empty? && hostname_resolution_queue.closed? + local_addrinfo ? + addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) : + addrinfo.connect(timeout: connect_timeout) + else + socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) + socket.bind(local_addrinfo) if local_addrinfo + socket.connect_nonblock(addrinfo, exception: false) + end + + case result + when 0 + connected_socket = socket + state = :success + when Socket + connected_socket = result + state = :success + when :wait_writable + connecting_sockets.add(socket, addrinfo) + state = :v46w + end + rescue SystemCallError => e + last_error = e + socket.close if socket && !socket.closed? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + end + + next + when :v46w + if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero? + state = :timeout + next + end + + remaining = second_to_timeout(connection_attempt_delay_expires_at) + hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting + hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining) + + if connectable_sockets&.any? + while (connectable_socket = connectable_sockets.pop) + is_connected = + if is_windows_environment + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME) + sockopt.unpack('i').first >= 0 + else + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) + sockopt.int.zero? + end + + if is_connected + connected_socket = connectable_socket + connecting_sockets.delete connectable_socket + connectable_sockets.each do |other_connectable_socket| + other_connectable_socket.close unless other_connectable_socket.closed? + end + state = :success + break + else + failed_ai = connecting_sockets.delete connectable_socket + inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address + last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int) + connectable_socket.close unless connectable_socket.closed? + + next if connectable_sockets.any? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Wait for connection attempt delay timeout in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + end + elsif hostname_resolved&.any? + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + else + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + state = :v46c + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + + next + when :success + break connected_socket + when :failure + raise last_error + when :timeout + raise Errno::ETIMEDOUT, 'user specified timeout' + end + end + + if block_given? + begin + yield ret + ensure + ret.close + end + else + ret + end + ensure + if fast_fallback + hostname_resolution_threads.each do |thread| + thread&.exit + end + + hostname_resolution_queue&.close_all + + connecting_sockets.each do |connecting_socket| + connecting_socket.close unless connecting_socket.closed? + end + end + end + + def self.specified_family_name_and_next_state(hostname) + if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c] + elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c] + end + end + private_class_method :specified_family_name_and_next_state + + def self.hostname_resolution(family, host, port, hostname_resolution_queue) + begin + resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM) + hostname_resolution_queue.add_resolved(family, resolved_addrinfos) + rescue => e + hostname_resolution_queue.add_error(family, e) + end + end + private_class_method :hostname_resolution + + def self.second_to_timeout(ends_at) + return 0 unless ends_at + + remaining = (ends_at - current_clocktime) + remaining.negative? ? 0 : remaining + end + private_class_method :second_to_timeout + + def self.current_clocktime + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + private_class_method :current_clocktime + + class SelectableAddrinfos + PRIORITY_ON_V6 = [:ipv6, :ipv4] + PRIORITY_ON_V4 = [:ipv4, :ipv6] + + def initialize + @addrinfo_dict = {} + @last_family = nil + end + + def add(family_name, addrinfos) + @addrinfo_dict[family_name] = addrinfos + end + + def get + return nil if empty? + + if @addrinfo_dict.size == 1 + @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift } + end + + precedences = case @last_family + when :ipv4, nil then PRIORITY_ON_V6 + when :ipv6 then PRIORITY_ON_V4 + end + + precedences.each do |family_name| + addrinfo = @addrinfo_dict[family_name]&.shift + next unless addrinfo + + @last_family = family_name + return addrinfo + end + end + + def empty? + @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? } + end + + def any? + !empty? + end + end + private_constant :SelectableAddrinfos + + class NoHostnameResolutionQueue + def waiting_pipe + nil + end + + def add_resolved(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def add_error(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def get + nil + end + + def opened? + false + end + + def closed? + true + end + + def close_all + # Do nothing + end + end + private_constant :NoHostnameResolutionQueue + + class HostnameResolutionQueue + def initialize(size) + @size = size + @taken_count = 0 + @rpipe, @wpipe = IO.pipe + @queue = Queue.new + @mutex = Mutex.new + end + + def waiting_pipe + [@rpipe] + end + + def add_resolved(family, resolved_addrinfos) + @mutex.synchronize do + @queue.push [family, resolved_addrinfos] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def add_error(family, error) + @mutex.synchronize do + @queue.push [family, error] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def get + return nil if @queue.empty? + + res = nil + + @mutex.synchronize do + @rpipe.getbyte + res = @queue.pop + end + + @taken_count += 1 + close_all if @taken_count == @size + res + end + + def closed? + @rpipe.closed? + end + + def opened? + !closed? + end + + def close_all + @queue.close unless @queue.closed? + @rpipe.close unless @rpipe.closed? + @wpipe.close unless @wpipe.closed? + end + end + private_constant :HostnameResolutionQueue + + class ConnectingSockets + def initialize + @socket_dict = {} + end + + def all + @socket_dict.keys + end + + def add(socket, addrinfo) + @socket_dict[socket] = addrinfo + end + + def delete(socket) + @socket_dict.delete socket + end + + def empty? + @socket_dict.empty? + end + + def each + @socket_dict.keys.each do |socket| + yield socket + end + end + end + private_constant :ConnectingSockets + + def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) last_error = nil ret = nil @@ -669,6 +1176,7 @@ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: ni ret end end + private_class_method :tcp_without_fast_fallback # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index 9150c3ff677903..04719fff28cfe0 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -669,6 +669,7 @@ def def_intern(func_name, pat, prefix_optional=nil) SO_RTABLE nil Set the routing table for this socket (OpenBSD) SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19) SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12) +SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows) SOPRI_INTERACTIVE nil Interactive socket priority SOPRI_NORMAL nil Normal socket priority diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 283735b12ce68c..f486db4262abb3 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -35,6 +35,7 @@ #ifdef _WIN32 # include # include +# include # include # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL diff --git a/include/ruby/win32.h b/include/ruby/win32.h index dfb56f418237bc..27a3467606cd44 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -35,6 +35,7 @@ extern "C++" { /* template without extern "C++" */ #endif #include #include +#include #if !defined(_MSC_VER) || _MSC_VER >= 1400 #include #endif diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index 598a05d123a571..6a057e866f3770 100644 --- a/test/socket/test_socket.rb +++ b/test/socket/test_socket.rb @@ -778,4 +778,243 @@ def test_resolurion_error_error_code end end + def test_tcp_socket_v6_hostname_resolved_earlier + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + server_thread = Thread.new { server.accept } + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(10); [Addrinfo.tcp("127.0.0.1", port)] + end + end + + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v4_hostname_resolved_earlier + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + server = TCPServer.new("127.0.0.1", 0) + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then sleep(10); [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv4?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v6_hostname_resolved_in_resolution_delay + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + port = server.addr[1] + delay_time = 0.025 # Socket::RESOLUTION_DELAY (private) is 0.05 + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then sleep(delay_time); [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v6_hostname_resolved_earlier_and_v6_server_is_not_listening + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + ipv4_address = "127.0.0.1" + ipv4_server = Socket.new(Socket::AF_INET, :STREAM) + ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address)) + port = ipv4_server.connect_address.ip_port + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(0.001); [Addrinfo.tcp(ipv4_address, port)] + end + end + + ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept } + socket = Socket.tcp("localhost", port) + assert_equal(ipv4_address, socket.remote_address.ip_address) + + accepted, _ = ipv4_server_thread.value + accepted.close + ipv4_server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_resolv_timeout + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep } + port = TCPServer.new("localhost", 0).addr[1] + + assert_raise(Errno::ETIMEDOUT) do + Socket.tcp("localhost", port, resolv_timeout: 0.01) + end + end; + end + + def test_tcp_socket_resolv_timeout_with_connection_failure + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + server = TCPServer.new("127.0.0.1", 12345) + _, port, = server.addr + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + if family == Socket::AF_INET6 + sleep + else + [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server.close + + assert_raise(Errno::ETIMEDOUT) do + Socket.tcp("localhost", port, resolv_timeout: 0.01) + end + end; + end + + def test_tcp_socket_one_hostname_resolution_succeeded_at_least + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(0.001); raise SocketError + end + end + + server_thread = Thread.new { server.accept } + socket = nil + + assert_nothing_raised do + socket = Socket.tcp("localhost", port) + end + + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_all_hostname_resolution_failed + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then raise SocketError + when Socket::AF_INET then sleep(0.001); raise SocketError, "Last hostname resolution error" + end + end + port = TCPServer.new("localhost", 0).addr[1] + + assert_raise_with_message(SocketError, "Last hostname resolution error") do + Socket.tcp("localhost", port) + end + end; + end + + def test_tcp_socket_v6_address_passed + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + _, port, = server.addr + + Addrinfo.define_singleton_method(:getaddrinfo) do |*_| + [Addrinfo.tcp("::1", port)] + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("::1", port) + + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_fast_fallback_is_false + server = TCPServer.new("127.0.0.1", 0) + _, port, = server.addr + server_thread = Thread.new { server.accept } + socket = Socket.tcp("127.0.0.1", port, fast_fallback: false) + + assert_true(socket.remote_address.ipv4?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end end if defined?(Socket) From a0f7de814ae5c299d6ce99bed5fb308a05d50ba0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 26 Feb 2024 12:29:23 +0900 Subject: [PATCH 079/147] [Bug #20296] Fix the default assertion message --- ext/socket/lib/socket.rb | 512 +------------------------------------ ext/socket/mkconstants.rb | 1 - ext/socket/rubysocket.h | 1 - include/ruby/win32.h | 1 - test/ruby/test_complex.rb | 2 +- test/socket/test_socket.rb | 239 ----------------- 6 files changed, 3 insertions(+), 753 deletions(-) diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index e953077fe6bbde..de542223c64399 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -599,30 +599,6 @@ def accept_nonblock(exception: true) __accept_nonblock(exception) end - RESOLUTION_DELAY = 0.05 - private_constant :RESOLUTION_DELAY - - CONNECTION_ATTEMPT_DELAY = 0.25 - private_constant :CONNECTION_ATTEMPT_DELAY - - ADDRESS_FAMILIES = { - ipv6: Socket::AF_INET6, - ipv4: Socket::AF_INET - }.freeze - private_constant :ADDRESS_FAMILIES - - HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0 - private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED - - IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/ - private_constant :IPV6_ADRESS_FORMAT - - @tcp_fast_fallback = true - - class << self - attr_accessor :tcp_fast_fallback - end - # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) @@ -648,491 +624,8 @@ class << self # sock.close_write # puts sock.read # } - def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket - unless fast_fallback - return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) - end - - # Happy Eyeballs' states - # - :start - # - :v6c - # - :v4w - # - :v4c - # - :v46c - # - :v46w - # - :success - # - :failure - # - :timeout - - specified_family_name = nil - hostname_resolution_threads = [] - hostname_resolution_queue = nil - hostname_resolution_waiting = nil - hostname_resolution_expires_at = nil - selectable_addrinfos = SelectableAddrinfos.new - connecting_sockets = ConnectingSockets.new - local_addrinfos = [] - connection_attempt_delay_expires_at = nil - connection_attempt_started_at = nil - state = :start - connected_socket = nil - last_error = nil - is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) - - ret = loop do - case state - when :start - specified_family_name, next_state = host && specified_family_name_and_next_state(host) - - if local_host && local_port - specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name - local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) - end - - if specified_family_name - addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) - selectable_addrinfos.add(specified_family_name, addrinfos) - hostname_resolution_queue = NoHostnameResolutionQueue.new - state = next_state - next - end - - resolving_family_names = ADDRESS_FAMILIES.keys - hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size) - hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe - hostname_resolution_started_at = current_clocktime if resolv_timeout - hostname_resolution_args = [host, port, hostname_resolution_queue] - - hostname_resolution_threads.concat( - resolving_family_names.map { |family| - thread_args = [family, *hostname_resolution_args] - thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) } - Thread.pass - thread - } - ) - - hostname_resolution_retry_count = resolving_family_names.size - 1 - hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout - - while hostname_resolution_retry_count >= 0 - remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil - hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining) - - unless hostname_resolved - state = :timeout - break - end - - family_name, res = hostname_resolution_queue.get - - if res.is_a? Exception - unless (Socket.const_defined?(:EAI_ADDRFAMILY)) && - (res.is_a?(Socket::ResolutionError)) && - (res.error_code == Socket::EAI_ADDRFAMILY) - last_error = res - end - - if hostname_resolution_retry_count.zero? - state = :failure - break - end - hostname_resolution_retry_count -= 1 - else - state = case family_name - when :ipv6 then :v6c - when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w - end - selectable_addrinfos.add(family_name, res) - last_error = nil - break - end - end - - next - when :v4w - ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY) - - if ipv6_resolved - family_name, res = hostname_resolution_queue.get - selectable_addrinfos.add(family_name, res) unless res.is_a? Exception - state = :v46c - else - state = :v4c - end - - next - when :v4c, :v6c, :v46c - connection_attempt_started_at = current_clocktime unless connection_attempt_started_at - addrinfo = selectable_addrinfos.get - - if local_addrinfos.any? - local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily } - - if local_addrinfo.nil? - if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? - last_error = SocketError.new 'no appropriate local address' - state = :failure - elsif selectable_addrinfos.any? - # Try other Addrinfo in next loop - else - if resolv_timeout && hostname_resolution_queue.opened? && - (current_clocktime >= hostname_resolution_expires_at) - state = :timeout - else - # Wait for connection to be established or hostname resolution in next loop - connection_attempt_delay_expires_at = nil - state = :v46w - end - end - next - end - end - - connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY - - begin - result = if specified_family_name && selectable_addrinfos.empty? && - connecting_sockets.empty? && hostname_resolution_queue.closed? - local_addrinfo ? - addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) : - addrinfo.connect(timeout: connect_timeout) - else - socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) - socket.bind(local_addrinfo) if local_addrinfo - socket.connect_nonblock(addrinfo, exception: false) - end - - case result - when 0 - connected_socket = socket - state = :success - when Socket - connected_socket = result - state = :success - when :wait_writable - connecting_sockets.add(socket, addrinfo) - state = :v46w - end - rescue SystemCallError => e - last_error = e - socket.close if socket && !socket.closed? - - if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? - state = :failure - elsif selectable_addrinfos.any? - # Try other Addrinfo in next loop - else - if resolv_timeout && hostname_resolution_queue.opened? && - (current_clocktime >= hostname_resolution_expires_at) - state = :timeout - else - # Wait for connection to be established or hostname resolution in next loop - connection_attempt_delay_expires_at = nil - state = :v46w - end - end - end - - next - when :v46w - if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero? - state = :timeout - next - end - - remaining = second_to_timeout(connection_attempt_delay_expires_at) - hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting - hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining) - - if connectable_sockets&.any? - while (connectable_socket = connectable_sockets.pop) - is_connected = - if is_windows_environment - sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME) - sockopt.unpack('i').first >= 0 - else - sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) - sockopt.int.zero? - end - - if is_connected - connected_socket = connectable_socket - connecting_sockets.delete connectable_socket - connectable_sockets.each do |other_connectable_socket| - other_connectable_socket.close unless other_connectable_socket.closed? - end - state = :success - break - else - failed_ai = connecting_sockets.delete connectable_socket - inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address - last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int) - connectable_socket.close unless connectable_socket.closed? - - next if connectable_sockets.any? - - if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? - state = :failure - elsif selectable_addrinfos.any? - # Wait for connection attempt delay timeout in next loop - else - if resolv_timeout && hostname_resolution_queue.opened? && - (current_clocktime >= hostname_resolution_expires_at) - state = :timeout - else - # Wait for connection to be established or hostname resolution in next loop - connection_attempt_delay_expires_at = nil - end - end - end - end - elsif hostname_resolved&.any? - family_name, res = hostname_resolution_queue.get - selectable_addrinfos.add(family_name, res) unless res.is_a? Exception - else - if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? - state = :failure - elsif selectable_addrinfos.any? - # Try other Addrinfo in next loop - state = :v46c - else - if resolv_timeout && hostname_resolution_queue.opened? && - (current_clocktime >= hostname_resolution_expires_at) - state = :timeout - else - # Wait for connection to be established or hostname resolution in next loop - connection_attempt_delay_expires_at = nil - end - end - end - - next - when :success - break connected_socket - when :failure - raise last_error - when :timeout - raise Errno::ETIMEDOUT, 'user specified timeout' - end - end - - if block_given? - begin - yield ret - ensure - ret.close - end - else - ret - end - ensure - if fast_fallback - hostname_resolution_threads.each do |thread| - thread&.exit - end - - hostname_resolution_queue&.close_all - - connecting_sockets.each do |connecting_socket| - connecting_socket.close unless connecting_socket.closed? - end - end - end - - def self.specified_family_name_and_next_state(hostname) - if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c] - elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c] - end - end - private_class_method :specified_family_name_and_next_state - - def self.hostname_resolution(family, host, port, hostname_resolution_queue) - begin - resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM) - hostname_resolution_queue.add_resolved(family, resolved_addrinfos) - rescue => e - hostname_resolution_queue.add_error(family, e) - end - end - private_class_method :hostname_resolution - - def self.second_to_timeout(ends_at) - return 0 unless ends_at - - remaining = (ends_at - current_clocktime) - remaining.negative? ? 0 : remaining - end - private_class_method :second_to_timeout - - def self.current_clocktime - Process.clock_gettime(Process::CLOCK_MONOTONIC) - end - private_class_method :current_clocktime - - class SelectableAddrinfos - PRIORITY_ON_V6 = [:ipv6, :ipv4] - PRIORITY_ON_V4 = [:ipv4, :ipv6] - - def initialize - @addrinfo_dict = {} - @last_family = nil - end - - def add(family_name, addrinfos) - @addrinfo_dict[family_name] = addrinfos - end - - def get - return nil if empty? - - if @addrinfo_dict.size == 1 - @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift } - end - - precedences = case @last_family - when :ipv4, nil then PRIORITY_ON_V6 - when :ipv6 then PRIORITY_ON_V4 - end - - precedences.each do |family_name| - addrinfo = @addrinfo_dict[family_name]&.shift - next unless addrinfo - - @last_family = family_name - return addrinfo - end - end - - def empty? - @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? } - end - - def any? - !empty? - end - end - private_constant :SelectableAddrinfos - - class NoHostnameResolutionQueue - def waiting_pipe - nil - end - - def add_resolved(_, _) - raise StandardError, "This #{self.class} cannot respond to:" - end - - def add_error(_, _) - raise StandardError, "This #{self.class} cannot respond to:" - end - - def get - nil - end - - def opened? - false - end - - def closed? - true - end - - def close_all - # Do nothing - end - end - private_constant :NoHostnameResolutionQueue - - class HostnameResolutionQueue - def initialize(size) - @size = size - @taken_count = 0 - @rpipe, @wpipe = IO.pipe - @queue = Queue.new - @mutex = Mutex.new - end - - def waiting_pipe - [@rpipe] - end - - def add_resolved(family, resolved_addrinfos) - @mutex.synchronize do - @queue.push [family, resolved_addrinfos] - @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED - end - end - - def add_error(family, error) - @mutex.synchronize do - @queue.push [family, error] - @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED - end - end - - def get - return nil if @queue.empty? - - res = nil - - @mutex.synchronize do - @rpipe.getbyte - res = @queue.pop - end - - @taken_count += 1 - close_all if @taken_count == @size - res - end - - def closed? - @rpipe.closed? - end - - def opened? - !closed? - end - - def close_all - @queue.close unless @queue.closed? - @rpipe.close unless @rpipe.closed? - @wpipe.close unless @wpipe.closed? - end - end - private_constant :HostnameResolutionQueue - - class ConnectingSockets - def initialize - @socket_dict = {} - end - - def all - @socket_dict.keys - end - - def add(socket, addrinfo) - @socket_dict[socket] = addrinfo - end - - def delete(socket) - @socket_dict.delete socket - end - - def empty? - @socket_dict.empty? - end - - def each - @socket_dict.keys.each do |socket| - yield socket - end - end - end - private_constant :ConnectingSockets - - def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) + # + def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil) # :yield: socket last_error = nil ret = nil @@ -1176,7 +669,6 @@ def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_t ret end end - private_class_method :tcp_without_fast_fallback # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index 04719fff28cfe0..9150c3ff677903 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -669,7 +669,6 @@ def def_intern(func_name, pat, prefix_optional=nil) SO_RTABLE nil Set the routing table for this socket (OpenBSD) SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19) SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12) -SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows) SOPRI_INTERACTIVE nil Interactive socket priority SOPRI_NORMAL nil Normal socket priority diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index f486db4262abb3..283735b12ce68c 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -35,7 +35,6 @@ #ifdef _WIN32 # include # include -# include # include # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 27a3467606cd44..dfb56f418237bc 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -35,7 +35,6 @@ extern "C++" { /* template without extern "C++" */ #endif #include #include -#include #if !defined(_MSC_VER) || _MSC_VER >= 1400 #include #endif diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index 3a9bad1416fcc1..8817a6287342b8 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -980,7 +980,7 @@ def test_Complex_with_invalid_exception } end - def assert_complex_with_exception(error, *args, message: nil) + def assert_complex_with_exception(error, *args, message: "") assert_raise(error, message) do Complex(*args, exception: true) end diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index 6a057e866f3770..598a05d123a571 100644 --- a/test/socket/test_socket.rb +++ b/test/socket/test_socket.rb @@ -778,243 +778,4 @@ def test_resolurion_error_error_code end end - def test_tcp_socket_v6_hostname_resolved_earlier - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - begin - server = TCPServer.new("::1", 0) - rescue Errno::EADDRNOTAVAIL # IPv6 is not supported - exit - end - - server_thread = Thread.new { server.accept } - port = server.addr[1] - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] - when Socket::AF_INET then sleep(10); [Addrinfo.tcp("127.0.0.1", port)] - end - end - - socket = Socket.tcp("localhost", port) - assert_true(socket.remote_address.ipv6?) - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_v4_hostname_resolved_earlier - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - server = TCPServer.new("127.0.0.1", 0) - port = server.addr[1] - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then sleep(10); [Addrinfo.tcp("::1", port)] - when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] - end - end - - server_thread = Thread.new { server.accept } - socket = Socket.tcp("localhost", port) - assert_true(socket.remote_address.ipv4?) - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_v6_hostname_resolved_in_resolution_delay - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - begin - server = TCPServer.new("::1", 0) - rescue Errno::EADDRNOTAVAIL # IPv6 is not supported - exit - end - - port = server.addr[1] - delay_time = 0.025 # Socket::RESOLUTION_DELAY (private) is 0.05 - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then sleep(delay_time); [Addrinfo.tcp("::1", port)] - when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] - end - end - - server_thread = Thread.new { server.accept } - socket = Socket.tcp("localhost", port) - assert_true(socket.remote_address.ipv6?) - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_v6_hostname_resolved_earlier_and_v6_server_is_not_listening - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - ipv4_address = "127.0.0.1" - ipv4_server = Socket.new(Socket::AF_INET, :STREAM) - ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address)) - port = ipv4_server.connect_address.ip_port - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] - when Socket::AF_INET then sleep(0.001); [Addrinfo.tcp(ipv4_address, port)] - end - end - - ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept } - socket = Socket.tcp("localhost", port) - assert_equal(ipv4_address, socket.remote_address.ip_address) - - accepted, _ = ipv4_server_thread.value - accepted.close - ipv4_server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_resolv_timeout - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep } - port = TCPServer.new("localhost", 0).addr[1] - - assert_raise(Errno::ETIMEDOUT) do - Socket.tcp("localhost", port, resolv_timeout: 0.01) - end - end; - end - - def test_tcp_socket_resolv_timeout_with_connection_failure - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - server = TCPServer.new("127.0.0.1", 12345) - _, port, = server.addr - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - if family == Socket::AF_INET6 - sleep - else - [Addrinfo.tcp("127.0.0.1", port)] - end - end - - server.close - - assert_raise(Errno::ETIMEDOUT) do - Socket.tcp("localhost", port, resolv_timeout: 0.01) - end - end; - end - - def test_tcp_socket_one_hostname_resolution_succeeded_at_least - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - begin - server = TCPServer.new("::1", 0) - rescue Errno::EADDRNOTAVAIL # IPv6 is not supported - exit - end - - port = server.addr[1] - - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] - when Socket::AF_INET then sleep(0.001); raise SocketError - end - end - - server_thread = Thread.new { server.accept } - socket = nil - - assert_nothing_raised do - socket = Socket.tcp("localhost", port) - end - - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_all_hostname_resolution_failed - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| - case family - when Socket::AF_INET6 then raise SocketError - when Socket::AF_INET then sleep(0.001); raise SocketError, "Last hostname resolution error" - end - end - port = TCPServer.new("localhost", 0).addr[1] - - assert_raise_with_message(SocketError, "Last hostname resolution error") do - Socket.tcp("localhost", port) - end - end; - end - - def test_tcp_socket_v6_address_passed - opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" - - begin; - begin - server = TCPServer.new("::1", 0) - rescue Errno::EADDRNOTAVAIL # IPv6 is not supported - exit - end - - _, port, = server.addr - - Addrinfo.define_singleton_method(:getaddrinfo) do |*_| - [Addrinfo.tcp("::1", port)] - end - - server_thread = Thread.new { server.accept } - socket = Socket.tcp("::1", port) - - assert_true(socket.remote_address.ipv6?) - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end; - end - - def test_tcp_socket_fast_fallback_is_false - server = TCPServer.new("127.0.0.1", 0) - _, port, = server.addr - server_thread = Thread.new { server.accept } - socket = Socket.tcp("127.0.0.1", port, fast_fallback: false) - - assert_true(socket.remote_address.ipv4?) - server_thread.value.close - server.close - socket.close if socket && !socket.closed? - end end if defined?(Socket) From d4e24021d39e1f80f0055b55d91f8d5f22e15084 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 26 Feb 2024 13:12:05 +0900 Subject: [PATCH 080/147] Revise 9ec342e07df6aa5e2c2e9003517753a2f1b508fd --- ext/socket/lib/socket.rb | 512 ++++++++++++++++++++++++++++++++++++- ext/socket/mkconstants.rb | 1 + ext/socket/rubysocket.h | 1 + include/ruby/win32.h | 1 + test/socket/test_socket.rb | 239 +++++++++++++++++ 5 files changed, 752 insertions(+), 2 deletions(-) diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index de542223c64399..e953077fe6bbde 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -599,6 +599,30 @@ def accept_nonblock(exception: true) __accept_nonblock(exception) end + RESOLUTION_DELAY = 0.05 + private_constant :RESOLUTION_DELAY + + CONNECTION_ATTEMPT_DELAY = 0.25 + private_constant :CONNECTION_ATTEMPT_DELAY + + ADDRESS_FAMILIES = { + ipv6: Socket::AF_INET6, + ipv4: Socket::AF_INET + }.freeze + private_constant :ADDRESS_FAMILIES + + HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0 + private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED + + IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/ + private_constant :IPV6_ADRESS_FORMAT + + @tcp_fast_fallback = true + + class << self + attr_accessor :tcp_fast_fallback + end + # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) @@ -624,8 +648,491 @@ def accept_nonblock(exception: true) # sock.close_write # puts sock.read # } - # - def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil) # :yield: socket + def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket + unless fast_fallback + return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) + end + + # Happy Eyeballs' states + # - :start + # - :v6c + # - :v4w + # - :v4c + # - :v46c + # - :v46w + # - :success + # - :failure + # - :timeout + + specified_family_name = nil + hostname_resolution_threads = [] + hostname_resolution_queue = nil + hostname_resolution_waiting = nil + hostname_resolution_expires_at = nil + selectable_addrinfos = SelectableAddrinfos.new + connecting_sockets = ConnectingSockets.new + local_addrinfos = [] + connection_attempt_delay_expires_at = nil + connection_attempt_started_at = nil + state = :start + connected_socket = nil + last_error = nil + is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) + + ret = loop do + case state + when :start + specified_family_name, next_state = host && specified_family_name_and_next_state(host) + + if local_host && local_port + specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name + local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + end + + if specified_family_name + addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout) + selectable_addrinfos.add(specified_family_name, addrinfos) + hostname_resolution_queue = NoHostnameResolutionQueue.new + state = next_state + next + end + + resolving_family_names = ADDRESS_FAMILIES.keys + hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size) + hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe + hostname_resolution_started_at = current_clocktime if resolv_timeout + hostname_resolution_args = [host, port, hostname_resolution_queue] + + hostname_resolution_threads.concat( + resolving_family_names.map { |family| + thread_args = [family, *hostname_resolution_args] + thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) } + Thread.pass + thread + } + ) + + hostname_resolution_retry_count = resolving_family_names.size - 1 + hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout + + while hostname_resolution_retry_count >= 0 + remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil + hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining) + + unless hostname_resolved + state = :timeout + break + end + + family_name, res = hostname_resolution_queue.get + + if res.is_a? Exception + unless (Socket.const_defined?(:EAI_ADDRFAMILY)) && + (res.is_a?(Socket::ResolutionError)) && + (res.error_code == Socket::EAI_ADDRFAMILY) + last_error = res + end + + if hostname_resolution_retry_count.zero? + state = :failure + break + end + hostname_resolution_retry_count -= 1 + else + state = case family_name + when :ipv6 then :v6c + when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w + end + selectable_addrinfos.add(family_name, res) + last_error = nil + break + end + end + + next + when :v4w + ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY) + + if ipv6_resolved + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + state = :v46c + else + state = :v4c + end + + next + when :v4c, :v6c, :v46c + connection_attempt_started_at = current_clocktime unless connection_attempt_started_at + addrinfo = selectable_addrinfos.get + + if local_addrinfos.any? + local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily } + + if local_addrinfo.nil? + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + last_error = SocketError.new 'no appropriate local address' + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + next + end + end + + connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY + + begin + result = if specified_family_name && selectable_addrinfos.empty? && + connecting_sockets.empty? && hostname_resolution_queue.closed? + local_addrinfo ? + addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) : + addrinfo.connect(timeout: connect_timeout) + else + socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) + socket.bind(local_addrinfo) if local_addrinfo + socket.connect_nonblock(addrinfo, exception: false) + end + + case result + when 0 + connected_socket = socket + state = :success + when Socket + connected_socket = result + state = :success + when :wait_writable + connecting_sockets.add(socket, addrinfo) + state = :v46w + end + rescue SystemCallError => e + last_error = e + socket.close if socket && !socket.closed? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + state = :v46w + end + end + end + + next + when :v46w + if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero? + state = :timeout + next + end + + remaining = second_to_timeout(connection_attempt_delay_expires_at) + hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting + hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining) + + if connectable_sockets&.any? + while (connectable_socket = connectable_sockets.pop) + is_connected = + if is_windows_environment + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME) + sockopt.unpack('i').first >= 0 + else + sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) + sockopt.int.zero? + end + + if is_connected + connected_socket = connectable_socket + connecting_sockets.delete connectable_socket + connectable_sockets.each do |other_connectable_socket| + other_connectable_socket.close unless other_connectable_socket.closed? + end + state = :success + break + else + failed_ai = connecting_sockets.delete connectable_socket + inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address + last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int) + connectable_socket.close unless connectable_socket.closed? + + next if connectable_sockets.any? + + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Wait for connection attempt delay timeout in next loop + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + end + elsif hostname_resolved&.any? + family_name, res = hostname_resolution_queue.get + selectable_addrinfos.add(family_name, res) unless res.is_a? Exception + else + if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed? + state = :failure + elsif selectable_addrinfos.any? + # Try other Addrinfo in next loop + state = :v46c + else + if resolv_timeout && hostname_resolution_queue.opened? && + (current_clocktime >= hostname_resolution_expires_at) + state = :timeout + else + # Wait for connection to be established or hostname resolution in next loop + connection_attempt_delay_expires_at = nil + end + end + end + + next + when :success + break connected_socket + when :failure + raise last_error + when :timeout + raise Errno::ETIMEDOUT, 'user specified timeout' + end + end + + if block_given? + begin + yield ret + ensure + ret.close + end + else + ret + end + ensure + if fast_fallback + hostname_resolution_threads.each do |thread| + thread&.exit + end + + hostname_resolution_queue&.close_all + + connecting_sockets.each do |connecting_socket| + connecting_socket.close unless connecting_socket.closed? + end + end + end + + def self.specified_family_name_and_next_state(hostname) + if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c] + elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c] + end + end + private_class_method :specified_family_name_and_next_state + + def self.hostname_resolution(family, host, port, hostname_resolution_queue) + begin + resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM) + hostname_resolution_queue.add_resolved(family, resolved_addrinfos) + rescue => e + hostname_resolution_queue.add_error(family, e) + end + end + private_class_method :hostname_resolution + + def self.second_to_timeout(ends_at) + return 0 unless ends_at + + remaining = (ends_at - current_clocktime) + remaining.negative? ? 0 : remaining + end + private_class_method :second_to_timeout + + def self.current_clocktime + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + private_class_method :current_clocktime + + class SelectableAddrinfos + PRIORITY_ON_V6 = [:ipv6, :ipv4] + PRIORITY_ON_V4 = [:ipv4, :ipv6] + + def initialize + @addrinfo_dict = {} + @last_family = nil + end + + def add(family_name, addrinfos) + @addrinfo_dict[family_name] = addrinfos + end + + def get + return nil if empty? + + if @addrinfo_dict.size == 1 + @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift } + end + + precedences = case @last_family + when :ipv4, nil then PRIORITY_ON_V6 + when :ipv6 then PRIORITY_ON_V4 + end + + precedences.each do |family_name| + addrinfo = @addrinfo_dict[family_name]&.shift + next unless addrinfo + + @last_family = family_name + return addrinfo + end + end + + def empty? + @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? } + end + + def any? + !empty? + end + end + private_constant :SelectableAddrinfos + + class NoHostnameResolutionQueue + def waiting_pipe + nil + end + + def add_resolved(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def add_error(_, _) + raise StandardError, "This #{self.class} cannot respond to:" + end + + def get + nil + end + + def opened? + false + end + + def closed? + true + end + + def close_all + # Do nothing + end + end + private_constant :NoHostnameResolutionQueue + + class HostnameResolutionQueue + def initialize(size) + @size = size + @taken_count = 0 + @rpipe, @wpipe = IO.pipe + @queue = Queue.new + @mutex = Mutex.new + end + + def waiting_pipe + [@rpipe] + end + + def add_resolved(family, resolved_addrinfos) + @mutex.synchronize do + @queue.push [family, resolved_addrinfos] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def add_error(family, error) + @mutex.synchronize do + @queue.push [family, error] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED + end + end + + def get + return nil if @queue.empty? + + res = nil + + @mutex.synchronize do + @rpipe.getbyte + res = @queue.pop + end + + @taken_count += 1 + close_all if @taken_count == @size + res + end + + def closed? + @rpipe.closed? + end + + def opened? + !closed? + end + + def close_all + @queue.close unless @queue.closed? + @rpipe.close unless @rpipe.closed? + @wpipe.close unless @wpipe.closed? + end + end + private_constant :HostnameResolutionQueue + + class ConnectingSockets + def initialize + @socket_dict = {} + end + + def all + @socket_dict.keys + end + + def add(socket, addrinfo) + @socket_dict[socket] = addrinfo + end + + def delete(socket) + @socket_dict.delete socket + end + + def empty? + @socket_dict.empty? + end + + def each + @socket_dict.keys.each do |socket| + yield socket + end + end + end + private_constant :ConnectingSockets + + def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block) last_error = nil ret = nil @@ -669,6 +1176,7 @@ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: ni ret end end + private_class_method :tcp_without_fast_fallback # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index 9150c3ff677903..04719fff28cfe0 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -669,6 +669,7 @@ def def_intern(func_name, pat, prefix_optional=nil) SO_RTABLE nil Set the routing table for this socket (OpenBSD) SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19) SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12) +SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows) SOPRI_INTERACTIVE nil Interactive socket priority SOPRI_NORMAL nil Normal socket priority diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 283735b12ce68c..f486db4262abb3 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -35,6 +35,7 @@ #ifdef _WIN32 # include # include +# include # include # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL diff --git a/include/ruby/win32.h b/include/ruby/win32.h index dfb56f418237bc..27a3467606cd44 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -35,6 +35,7 @@ extern "C++" { /* template without extern "C++" */ #endif #include #include +#include #if !defined(_MSC_VER) || _MSC_VER >= 1400 #include #endif diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index 598a05d123a571..6a057e866f3770 100644 --- a/test/socket/test_socket.rb +++ b/test/socket/test_socket.rb @@ -778,4 +778,243 @@ def test_resolurion_error_error_code end end + def test_tcp_socket_v6_hostname_resolved_earlier + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + server_thread = Thread.new { server.accept } + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(10); [Addrinfo.tcp("127.0.0.1", port)] + end + end + + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v4_hostname_resolved_earlier + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + server = TCPServer.new("127.0.0.1", 0) + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then sleep(10); [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv4?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v6_hostname_resolved_in_resolution_delay + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + port = server.addr[1] + delay_time = 0.025 # Socket::RESOLUTION_DELAY (private) is 0.05 + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then sleep(delay_time); [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("localhost", port) + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_v6_hostname_resolved_earlier_and_v6_server_is_not_listening + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + ipv4_address = "127.0.0.1" + ipv4_server = Socket.new(Socket::AF_INET, :STREAM) + ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address)) + port = ipv4_server.connect_address.ip_port + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(0.001); [Addrinfo.tcp(ipv4_address, port)] + end + end + + ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept } + socket = Socket.tcp("localhost", port) + assert_equal(ipv4_address, socket.remote_address.ip_address) + + accepted, _ = ipv4_server_thread.value + accepted.close + ipv4_server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_resolv_timeout + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep } + port = TCPServer.new("localhost", 0).addr[1] + + assert_raise(Errno::ETIMEDOUT) do + Socket.tcp("localhost", port, resolv_timeout: 0.01) + end + end; + end + + def test_tcp_socket_resolv_timeout_with_connection_failure + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + server = TCPServer.new("127.0.0.1", 12345) + _, port, = server.addr + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + if family == Socket::AF_INET6 + sleep + else + [Addrinfo.tcp("127.0.0.1", port)] + end + end + + server.close + + assert_raise(Errno::ETIMEDOUT) do + Socket.tcp("localhost", port, resolv_timeout: 0.01) + end + end; + end + + def test_tcp_socket_one_hostname_resolution_succeeded_at_least + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + port = server.addr[1] + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)] + when Socket::AF_INET then sleep(0.001); raise SocketError + end + end + + server_thread = Thread.new { server.accept } + socket = nil + + assert_nothing_raised do + socket = Socket.tcp("localhost", port) + end + + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_all_hostname_resolution_failed + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then raise SocketError + when Socket::AF_INET then sleep(0.001); raise SocketError, "Last hostname resolution error" + end + end + port = TCPServer.new("localhost", 0).addr[1] + + assert_raise_with_message(SocketError, "Last hostname resolution error") do + Socket.tcp("localhost", port) + end + end; + end + + def test_tcp_socket_v6_address_passed + opts = %w[-rsocket -W1] + assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + + begin; + begin + server = TCPServer.new("::1", 0) + rescue Errno::EADDRNOTAVAIL # IPv6 is not supported + exit + end + + _, port, = server.addr + + Addrinfo.define_singleton_method(:getaddrinfo) do |*_| + [Addrinfo.tcp("::1", port)] + end + + server_thread = Thread.new { server.accept } + socket = Socket.tcp("::1", port) + + assert_true(socket.remote_address.ipv6?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end; + end + + def test_tcp_socket_fast_fallback_is_false + server = TCPServer.new("127.0.0.1", 0) + _, port, = server.addr + server_thread = Thread.new { server.accept } + socket = Socket.tcp("127.0.0.1", port, fast_fallback: false) + + assert_true(socket.remote_address.ipv4?) + server_thread.value.close + server.close + socket.close if socket && !socket.closed? + end end if defined?(Socket) From 459198999e57652e32817b566ad47443f4bbcedc Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Sat, 24 Feb 2024 10:09:06 +0900 Subject: [PATCH 081/147] Expand Launchable into ubuntu workflow --- .../actions/launchable/record-test/action.yml | 33 ++++++++ .github/actions/launchable/setup/action.yml | 84 +++++++++++++++++++ .github/workflows/macos.yml | 73 +++------------- .github/workflows/ubuntu.yml | 16 ++++ 4 files changed, 146 insertions(+), 60 deletions(-) create mode 100644 .github/actions/launchable/record-test/action.yml create mode 100644 .github/actions/launchable/setup/action.yml diff --git a/.github/actions/launchable/record-test/action.yml b/.github/actions/launchable/record-test/action.yml new file mode 100644 index 00000000000000..e12f1dc9f4cd15 --- /dev/null +++ b/.github/actions/launchable/record-test/action.yml @@ -0,0 +1,33 @@ +name: Record tests in Launchable +description: >- + Upload the test results to Launchable + +inputs: + os: + required: true + description: An operating system that CI runs on. This value is used in Launchable flavor. + + report-path: + default: launchable_reports.json + required: true + description: A file path of the test report for uploading to Launchable + + test-opts: + default: none + required: false + description: >- + Test options that determine how tests are run. + This value is used in the Launchable flavor. + +outputs: {} # nothing? + +runs: + using: composite + + steps: + - name: Launchable - record tests + working-directory: ${{ inputs.builddir }} + shell: bash + run: | + test_opts="$(echo ${{ inputs.test-opts }} | sed 's/=/:/g' | sed 's/ //g')" + launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ matrix.test_task }} --flavor test_opts=${test_opts} raw ${{ inputs.report-path }} diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml new file mode 100644 index 00000000000000..6931d23ea440c7 --- /dev/null +++ b/.github/actions/launchable/setup/action.yml @@ -0,0 +1,84 @@ +name: Set up Launchable +description: >- + Install the required dependencies and execute the necessary Launchable commands for test recording + +inputs: + report-path: + default: launchable_reports.json + required: true + description: The file path of the test report for uploading to Launchable + + launchable-token: + required: false + description: >- + Launchable token is needed if you want to run Launchable on your forked repository. + See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details. + +outputs: + enable-launchable: + description: "The boolean value indicating whether Launchable is enabled or not" + value: ${{ steps.enable-launchable.outputs.enable-launchable }} + +runs: + using: composite + + steps: + - name: Enable Launchable conditionally + id: enable-launchable + run: echo "enable-launchable=true" >> $GITHUB_OUTPUT + shell: bash + if: >- + ${{ + (github.repository == 'ruby/ruby' || + (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)) && + (matrix.test_task == 'check' || matrix.test_task == 'test-all') + }} + + # Launchable CLI requires Python and Java. + # https://www.launchableinc.com/docs/resources/cli-reference/ + - name: Set up Python + uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 + with: + python-version: "3.x" + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set up Java + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'temurin' + java-version: '17' + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set environment variables for Launchable + shell: bash + run: | + : # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42 + echo "GITHUB_PULL_REQUEST_URL=${{ github.event.pull_request.html_url }}" >> $GITHUB_ENV + : # The following envs are necessary in Launchable tokenless authentication. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20 + echo "LAUNCHABLE_ORGANIZATION=${{ github.repository_owner }}" >> $GITHUB_ENV + echo "LAUNCHABLE_WORKSPACE=${{ github.event.repository.name }}" >> $GITHUB_ENV + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71 + echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV + echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set up Launchable + shell: bash + run: | + set -x + PATH=$PATH:$(python -msite --user-base)/bin + echo "PATH=$PATH" >> $GITHUB_ENV + pip install --user launchable + launchable verify + : # The build name cannot include a slash, so we replace the string here. + github_ref="$(echo ${{ github.ref }} | sed 's/\//_/g')" + : # With the --name option, we need to configure a unique identifier for this build. + : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here. + : # + : # FIXME: Need to fix `WARNING: Failed to process a change to a file`. + : # https://github.com/launchableinc/cli/issues/786 + launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA} + echo "TESTS=${TESTS} --launchable-test-reports=${{ inputs.report-path }}" >> $GITHUB_ENV + if: steps.enable-launchable.outputs.enable-launchable diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 9e720fcec04d19..f8c5b21e75a0b6 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -13,21 +13,6 @@ on: # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: -env: - # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App. - # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42 - GITHUB_PULL_REQUEST_URL: ${{ github.event.pull_request.html_url }} - # The following envs are necessary in Launchable tokenless authentication. - # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20 - LAUNCHABLE_ORGANIZATION: ${{ github.repository_owner }} - LAUNCHABLE_WORKSPACE: ${{ github.event.repository.name }} - # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71 - GITHUB_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - # This secret setting is needed if you want to run Launchable on your forked - # repository. - # See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details. - LAUNCHABLE_TOKEN: ${{ secrets.LAUNCHABLE_TOKEN }} - concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} @@ -67,17 +52,6 @@ jobs: )}} steps: - - name: Enable Launchable conditionally - id: enable_launchable - run: echo "enable_launchable=true" >> $GITHUB_OUTPUT - working-directory: - if: >- - ${{ - (github.repository == 'ruby/ruby' || - (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)) && - (matrix.test_task == 'check' || matrix.test_task == 'test-all') - }} - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: sparse-checkout-cone-mode: false @@ -110,38 +84,11 @@ jobs: echo "TESTS=${TESTS}" >> $GITHUB_ENV if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} - # Launchable CLI requires Python and Java - # https://www.launchableinc.com/docs/resources/cli-reference/ - - name: Set up Python - uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 - with: - python-version: "3.x" - if: steps.enable_launchable.outputs.enable_launchable - - - name: Set up Java - uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 - with: - distribution: 'temurin' - java-version: '17' - if: steps.enable_launchable.outputs.enable_launchable - - name: Set up Launchable - run: | - set -x - PATH=$PATH:$(python -msite --user-base)/bin - echo "PATH=$PATH" >> $GITHUB_ENV - pip install --user launchable - launchable verify - : # The build name cannot include a slash, so we replace the string here. - github_ref="$(echo ${{ github.ref }} | sed 's/\//_/g')" - : # With the --name option, we need to configure a unique identifier for this build. - : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here. - : # - : # FIXME: Need to fix `WARNING: Failed to process a change to a file`. - : # https://github.com/launchableinc/cli/issues/786 - launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA} - echo "TESTS=${TESTS} --launchable-test-reports=launchable_reports.json" >> $GITHUB_ENV - if: steps.enable_launchable.outputs.enable_launchable + id: enable-launchable + uses: ./.github/actions/launchable/setup + with: + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} - name: Set extra test options run: echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV @@ -166,9 +113,15 @@ jobs: if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} - - name: Launchable - record tests - run: launchable record tests --flavor os=${{ matrix.os }} --flavor test_task=${{ matrix.test_task }} raw launchable_reports.json - if: ${{ always() && steps.enable_launchable.outputs.enable_launchable }} + - name: Record test results in Launchable + uses: ./.github/actions/launchable/record-test + with: + # We need to configure the `build` directory because + # this composite action is executed in the default working directory. + report-path: build/launchable_reports.json + os: ${{ matrix.os }} + test-opts: ${{ matrix.test_opts }} + if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }} - uses: ./.github/actions/slack with: diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 316cd3786d5312..80af27bc1ac1b8 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -95,6 +95,12 @@ jobs: echo "TESTS=${TESTS}" >> $GITHUB_ENV if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + - name: Set up Launchable + id: enable-launchable + uses: ./.github/actions/launchable/setup + with: + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + - name: make ${{ matrix.test_task }} run: >- $SETARCH make -s ${{ matrix.test_task }} @@ -115,6 +121,16 @@ jobs: if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + - name: Record test results in Launchable + uses: ./.github/actions/launchable/record-test + with: + # We need to configure the `build` directory because + # this composite action is executed in the default working directory. + report-path: build/launchable_reports.json + os: ubuntu-20.04 + test-opts: ${{ matrix.configure }} + if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }} + - uses: ./.github/actions/slack with: label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} From 91ec1fc4e79d0070a029e6bd006afe04cdf26c9f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 26 Feb 2024 15:27:26 +0900 Subject: [PATCH 082/147] Revert "Revert rubygems tempdir check" This reverts commit 6aa5067ab970e70693529cde5102fab587158f7f. --- test/rubygems/helper.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index b917e1f396e193..c33d1bba215a87 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -76,6 +76,8 @@ class Gem::TestCase < Test::Unit::TestCase attr_accessor :uri # :nodoc: + @@tempdirs = [] + def assert_activate(expected, *specs) specs.each do |spec| case spec @@ -287,7 +289,8 @@ def setup FileUtils.mkdir_p @tmp - @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) + @tempdir = Dir.mktmpdir(method_name.to_s, @tmp) + @@tempdirs << @tempdir ENV["GEM_VENDOR"] = nil ENV["GEMRC"] = nil @@ -471,6 +474,8 @@ def teardown end @back_ui.close + + assert_empty @@tempdirs.select {|tempdir| File.exist?(tempdir) } end def credential_setup From 65f40967d5c2ee2df1755f8a9159553df15e6295 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 21 Feb 2024 22:35:14 +0900 Subject: [PATCH 083/147] [rubygems/rubygems] Get rid of too long paths This is a fix-up of #7483. Test method names in Rubygems are often very long, and the path under the temporary directory generated from them can easily exceed system limits. Even without including the method name in the path name, by saving the method and path name pair, it is possible to find the method from the remaining path name. https://github.com/rubygems/rubygems/commit/de55064a3d --- test/rubygems/helper.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index c33d1bba215a87..6b4aaa5525930c 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -289,8 +289,8 @@ def setup FileUtils.mkdir_p @tmp - @tempdir = Dir.mktmpdir(method_name.to_s, @tmp) - @@tempdirs << @tempdir + @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) + @@tempdirs << [method_name, @tempdir] ENV["GEM_VENDOR"] = nil ENV["GEMRC"] = nil @@ -475,7 +475,13 @@ def teardown @back_ui.close - assert_empty @@tempdirs.select {|tempdir| File.exist?(tempdir) } + ghosts = @@tempdirs.filter_map do |test_name, tempdir| + if File.exist?(tempdir) + FileUtils.rm_rf(tempdir) + test_name + end + end + assert_empty ghosts end def credential_setup From 7dd4b30b77241965fe94f173c382d0f8766d1fd3 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 23 Feb 2024 01:46:01 +0900 Subject: [PATCH 084/147] [rubygems/rubygems] The temporary directory must been removed On Windows, open files cannot be removed and `FileUtils.rm_rf` just silently fails. This means also handle leaks, not only temporary file leaks. https://github.com/rubygems/rubygems/commit/80a9c3ec08 --- test/rubygems/helper.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 6b4aaa5525930c..9ca2e269e30d27 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -290,7 +290,6 @@ def setup FileUtils.mkdir_p @tmp @tempdir = Dir.mktmpdir("test_rubygems_", @tmp) - @@tempdirs << [method_name, @tempdir] ENV["GEM_VENDOR"] = nil ENV["GEMRC"] = nil @@ -475,12 +474,11 @@ def teardown @back_ui.close + refute_directory_exists @tempdir, "may be still in use" ghosts = @@tempdirs.filter_map do |test_name, tempdir| - if File.exist?(tempdir) - FileUtils.rm_rf(tempdir) - test_name - end + test_name if File.exist?(tempdir) end + @@tempdirs << [method_name, @tempdir] assert_empty ghosts end From 7176c186d0d794bf89eac0645205c3f3d2d40f2d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 23 Feb 2024 01:51:23 +0900 Subject: [PATCH 085/147] [rubygems/rubygems] Fix `Fiddle::Handle` leaks Windows disallows to unlink opened files. https://github.com/rubygems/rubygems/commit/e0b63754bf --- test/rubygems/test_gem_ext_cargo_builder.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/rubygems/test_gem_ext_cargo_builder.rb b/test/rubygems/test_gem_ext_cargo_builder.rb index 0d893f54242d3f..5faf3e24807782 100644 --- a/test/rubygems/test_gem_ext_cargo_builder.rb +++ b/test/rubygems/test_gem_ext_cargo_builder.rb @@ -152,12 +152,16 @@ def assert_ffi_handle(bundle, name) require "fiddle" dylib_handle = Fiddle.dlopen bundle assert_nothing_raised { dylib_handle[name] } + ensure + dylib_handle&.close end def refute_ffi_handle(bundle, name) require "fiddle" dylib_handle = Fiddle.dlopen bundle assert_raise { dylib_handle[name] } + ensure + dylib_handle&.close end def replace_in_rust_file(name, from, to) From 164e464b042239cdbd14d3751a7f907754d580ce Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 25 Feb 2024 16:45:08 -0800 Subject: [PATCH 086/147] [ruby/strscan] Add a method for peeking and reading bytes as integers (https://github.com/ruby/strscan/pull/89) This commit adds `scan_byte` and `peek_byte`. `scan_byte` will scan the current byte, return it as an integer, and advance the cursor. `peek_byte` will return the current byte as an integer without advancing the cursor. Currently `StringScanner#get_byte` returns a string, but I want to get the current byte without allocating a string. I think this will help with writing high performance lexers. --------- https://github.com/ruby/strscan/commit/873aba2e5d Co-authored-by: Sutou Kouhei --- ext/strscan/strscan.c | 55 ++++++++++++++++++++++++++++++ test/strscan/test_stringscanner.rb | 23 +++++++++++++ 2 files changed, 78 insertions(+) diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index bed1c87cdc46a2..70a3ce52607d7e 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -902,6 +902,57 @@ strscan_getch(VALUE self) adjust_register_position(p, p->regs.end[0])); } +/* + * Scans one byte and returns it as an integer. + * This method is not multibyte character sensitive. + * See also: #getch. + * + * s = StringScanner.new('ab') + * s.scan_byte # => 97 + * s.scan_byte # => 98 + * s.scan_byte # => nil + * + * s = StringScanner.new("\244\242".force_encoding("euc-jp")) + * s.scan_byte # => 0xA4 + * s.scan_byte # => 0xA2 + * s.scan_byte # => nil + */ +static VALUE +strscan_scan_byte(VALUE self) +{ + struct strscanner *p; + + GET_SCANNER(self, p); + CLEAR_MATCH_STATUS(p); + if (EOS_P(p)) + return Qnil; + + VALUE byte = INT2FIX((unsigned char)*CURPTR(p)); + p->prev = p->curr; + p->curr++; + MATCHED(p); + adjust_registers_to_matched(p); + return byte; +} + +/* + * Peeks at the current byte and returns it as an integer. + * + * s = StringScanner.new('ab') + * s.peek_byte # => 97 + */ +static VALUE +strscan_peek_byte(VALUE self) +{ + struct strscanner *p; + + GET_SCANNER(self, p); + if (EOS_P(p)) + return Qnil; + + return INT2FIX((unsigned char)*CURPTR(p)); +} + /* * Scans one byte and returns it. * This method is not multibyte character sensitive. @@ -1605,6 +1656,7 @@ strscan_named_captures(VALUE self) * * - #getch * - #get_byte + * - #scan_byte * - #scan * - #scan_until * - #skip @@ -1617,6 +1669,7 @@ strscan_named_captures(VALUE self) * - #exist? * - #match? * - #peek + * - #peek_byte * * === Finding Where we Are * @@ -1708,7 +1761,9 @@ Init_strscan(void) rb_define_method(StringScanner, "getch", strscan_getch, 0); rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0); rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0); + rb_define_method(StringScanner, "scan_byte", strscan_scan_byte, 0); rb_define_method(StringScanner, "peek", strscan_peek, 1); + rb_define_method(StringScanner, "peek_byte", strscan_peek_byte, 0); rb_define_method(StringScanner, "peep", strscan_peep, 1); rb_define_method(StringScanner, "unscan", strscan_unscan, 0); diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 2a127a773a3698..2884b8ef054ff7 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -8,6 +8,29 @@ require 'test/unit' module StringScannerTests + def test_peek_byte + s = create_string_scanner('ab') + assert_equal 97, s.peek_byte + assert_equal 97, s.scan_byte + assert_equal 98, s.peek_byte + assert_equal 98, s.scan_byte + assert_nil s.peek_byte + assert_nil s.scan_byte + end + + def test_scan_byte + s = create_string_scanner('ab') + assert_equal 97, s.scan_byte + assert_equal 98, s.scan_byte + assert_nil s.scan_byte + + str = "\244\242".dup.force_encoding("euc-jp") + s = StringScanner.new(str) + assert_equal str.getbyte(s.pos), s.scan_byte + assert_equal str.getbyte(s.pos), s.scan_byte + assert_nil s.scan_byte + end + def test_s_new s = create_string_scanner('test string') assert_instance_of StringScanner, s From 38e3ad267569f38336458d461791b4a1cd79b5d1 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 17:03:10 +0900 Subject: [PATCH 087/147] Update gemspec according to the recent bundler template --- lib/tempfile.gemspec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec index a3cb11296d057e..efbca0bda75e7d 100644 --- a/lib/tempfile.gemspec +++ b/lib/tempfile.gemspec @@ -22,8 +22,11 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + spec.files = Dir.chdir(__dir__) do + `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject do |f| + (File.expand_path(f) == __FILE__) || + f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) + end end spec.require_paths = ["lib"] end From dddf62426b7a384715dd558773723ecbdfa37a11 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 25 Feb 2024 17:14:52 +0900 Subject: [PATCH 088/147] [ruby/tempfile] Use `IO.popen` to list files - Redirect `git ls-files` without shelling out. - When building by `gem`, `__FILE__` is the path name given in the command line, or the gemspec file name in the current directory. In that case, comparison it and expanded path never equal. Compare listed file names with the base name of `__FILE__` instead. https://github.com/ruby/tempfile/commit/ac5bab8c7a --- lib/tempfile.gemspec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec index efbca0bda75e7d..0b4c6cc8867b8c 100644 --- a/lib/tempfile.gemspec +++ b/lib/tempfile.gemspec @@ -22,9 +22,10 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(__dir__) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject do |f| - (File.expand_path(f) == __FILE__) || + gemspec = File.basename(__FILE__) + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| + ls.readlines("\x0", chomp: true).reject do |f| + (f == gemspec) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) end end From 1ca3482e0a7a6a528a648ce285dc344b0f6eef14 Mon Sep 17 00:00:00 2001 From: Pierrick Bouvier Date: Mon, 26 Feb 2024 11:03:12 +0400 Subject: [PATCH 089/147] Fix compilation for platforms without pthread Found when compiling ruby for windows-arm64 using msys2 Missing return type for function Init_lock_native_thread lock_native_thread.c:45:1: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] 45 | Init_lock_native_thread(void) | ^ | int --- ext/-test-/thread/lock_native_thread/lock_native_thread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/-test-/thread/lock_native_thread/lock_native_thread.c b/ext/-test-/thread/lock_native_thread/lock_native_thread.c index 74bc1b06fae784..2eb75809a9a57e 100644 --- a/ext/-test-/thread/lock_native_thread/lock_native_thread.c +++ b/ext/-test-/thread/lock_native_thread/lock_native_thread.c @@ -42,6 +42,7 @@ Init_lock_native_thread(void) } #else // HAVE_PTHREAD_H +void Init_lock_native_thread(void) { // do nothing From 40c9a3dad5bc18213eb9b5ad21aa00580c12c77b Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 26 Feb 2024 14:45:28 +0100 Subject: [PATCH 090/147] Update to ruby/mspec@36e8ed8 --- spec/mspec/spec/integration/run_spec.rb | 9 +++++---- spec/mspec/spec/integration/tag_spec.rb | 9 +++++---- spec/mspec/spec/spec_helper.rb | 2 ++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/spec/mspec/spec/integration/run_spec.rb b/spec/mspec/spec/integration/run_spec.rb index 90dc051543853e..ea0735e9b289f4 100644 --- a/spec/mspec/spec/integration/run_spec.rb +++ b/spec/mspec/spec/integration/run_spec.rb @@ -1,20 +1,21 @@ require 'spec_helper' RSpec.describe "Running mspec" do + q = BACKTRACE_QUOTE a_spec_output = <' -CWD/spec/fixtures/a_spec.rb:2:in `' +CWD/spec/fixtures/a_spec.rb:8:in #{q}block (2 levels) in ' +CWD/spec/fixtures/a_spec.rb:2:in #{q}' 2) Foo#bar fails ERROR RuntimeError: failure -CWD/spec/fixtures/a_spec.rb:12:in `block (2 levels) in ' -CWD/spec/fixtures/a_spec.rb:2:in `' +CWD/spec/fixtures/a_spec.rb:12:in #{q}block (2 levels) in ' +CWD/spec/fixtures/a_spec.rb:2:in #{q}' Finished in D.DDDDDD seconds EOS diff --git a/spec/mspec/spec/integration/tag_spec.rb b/spec/mspec/spec/integration/tag_spec.rb index 33df1cfd4067f8..ae08e9d45f8ef9 100644 --- a/spec/mspec/spec/integration/tag_spec.rb +++ b/spec/mspec/spec/integration/tag_spec.rb @@ -13,6 +13,7 @@ it "tags the failing specs" do fixtures = "spec/fixtures" out, ret = run_mspec("tag", "--add fails --fail #{fixtures}/tagging_spec.rb") + q = BACKTRACE_QUOTE expect(out).to eq <' -CWD/spec/fixtures/tagging_spec.rb:3:in `' +CWD/spec/fixtures/tagging_spec.rb:9:in #{q}block (2 levels) in ' +CWD/spec/fixtures/tagging_spec.rb:3:in #{q}' 2) Tag#me érròrs in unicode FAILED Expected 1 == 2 to be truthy but was false -CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in ' -CWD/spec/fixtures/tagging_spec.rb:3:in `' +CWD/spec/fixtures/tagging_spec.rb:13:in #{q}block (2 levels) in ' +CWD/spec/fixtures/tagging_spec.rb:3:in #{q}' Finished in D.DDDDDD seconds diff --git a/spec/mspec/spec/spec_helper.rb b/spec/mspec/spec/spec_helper.rb index 3a749581eee710..5cabfe5626448b 100644 --- a/spec/mspec/spec/spec_helper.rb +++ b/spec/mspec/spec/spec_helper.rb @@ -66,3 +66,5 @@ def ensure_mspec_method(method) include MSpecMatchers public :raise_error }.new + +BACKTRACE_QUOTE = RUBY_VERSION >= "3.4" ? "'" : "`" From 815db5c0289f5bbea2af275933ba6a4bf60a6967 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Mon, 26 Feb 2024 14:45:30 +0100 Subject: [PATCH 091/147] Update to ruby/spec@3a510bb --- spec/ruby/.rubocop_todo.yml | 1 - spec/ruby/core/encoding/replicate_spec.rb | 5 + spec/ruby/core/enumerable/fixtures/classes.rb | 6 + spec/ruby/core/enumerable/to_set_spec.rb | 29 +++++ spec/ruby/core/file/lutime_spec.rb | 9 +- spec/ruby/core/file/shared/update_time.rb | 105 ++++++++++++++++++ spec/ruby/core/file/utime_spec.rb | 100 +---------------- spec/ruby/core/filetest/exist_spec.rb | 8 ++ spec/ruby/core/kernel/not_match_spec.rb | 14 +++ spec/ruby/core/method/parameters_spec.rb | 16 +++ spec/ruby/core/proc/parameters_spec.rb | 14 +++ spec/ruby/core/string/to_i_spec.rb | 12 ++ spec/ruby/library/net-ftp/connect_spec.rb | 2 +- spec/ruby/library/set/set_spec.rb | 12 ++ spec/ruby/optional/capi/encoding_spec.rb | 31 +++++- spec/ruby/optional/capi/ext/encoding_spec.c | 5 + spec/ruby/optional/capi/ext/string_spec.c | 16 ++- spec/ruby/optional/capi/string_spec.rb | 74 ++++++++---- 18 files changed, 329 insertions(+), 130 deletions(-) create mode 100644 spec/ruby/core/enumerable/to_set_spec.rb create mode 100644 spec/ruby/core/file/shared/update_time.rb create mode 100644 spec/ruby/library/set/set_spec.rb diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml index a59e64bd58b6e0..3ebb23a8bb7f55 100644 --- a/spec/ruby/.rubocop_todo.yml +++ b/spec/ruby/.rubocop_todo.yml @@ -63,7 +63,6 @@ Lint/LiteralInInterpolation: - 'language/string_spec.rb' - 'language/symbol_spec.rb' - 'language/undef_spec.rb' - - 'library/net/ftp/connect_spec.rb' # Offense count: 8 # Cop supports --auto-correct. diff --git a/spec/ruby/core/encoding/replicate_spec.rb b/spec/ruby/core/encoding/replicate_spec.rb index 498d03581ac6e5..68c285158d386c 100644 --- a/spec/ruby/core/encoding/replicate_spec.rb +++ b/spec/ruby/core/encoding/replicate_spec.rb @@ -73,6 +73,11 @@ Encoding::US_ASCII.replicate('MY-US-ASCII') }.should complain(/warning: Encoding#replicate is deprecated and will be removed in Ruby 3.3; use the original encoding instead/) end + + it "raises EncodingError if too many encodings" do + code = '1_000.times {|i| Encoding::US_ASCII.replicate("R_#{i}") }' + ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)') + end end ruby_version_is "3.3" do diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb index fb4951c6e626a0..2701c6999c437a 100644 --- a/spec/ruby/core/enumerable/fixtures/classes.rb +++ b/spec/ruby/core/enumerable/fixtures/classes.rb @@ -342,4 +342,10 @@ def ===(*args) @block.call(*args) end end + + # Set is a core class since Ruby 3.2 + ruby_version_is '3.2' do + class SetSubclass < Set + end + end end # EnumerableSpecs utility classes diff --git a/spec/ruby/core/enumerable/to_set_spec.rb b/spec/ruby/core/enumerable/to_set_spec.rb new file mode 100644 index 00000000000000..c21a2772c4785d --- /dev/null +++ b/spec/ruby/core/enumerable/to_set_spec.rb @@ -0,0 +1,29 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is "3.2" do + describe "Enumerable#to_set" do + it "returns a new Set created from self" do + [1, 2, 3].to_set.should == Set[1, 2, 3] + {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]] + end + + it "passes down passed blocks" do + [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9] + end + + it "instantiates an object of provided as the first argument set class" do + set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass) + set.should be_kind_of(EnumerableSpecs::SetSubclass) + set.to_a.sort.should == [1, 2, 3] + end + + it "does not need explicit `require 'set'`" do + output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1') + puts [1, 2, 3].to_set + RUBY + + output.chomp.should == "#" + end + end +end diff --git a/spec/ruby/core/file/lutime_spec.rb b/spec/ruby/core/file/lutime_spec.rb index 1f0625f61ebc2f..0f6df42ea37df5 100644 --- a/spec/ruby/core/file/lutime_spec.rb +++ b/spec/ruby/core/file/lutime_spec.rb @@ -1,7 +1,12 @@ require_relative '../../spec_helper' +require_relative 'shared/update_time' -describe "File.lutime" do - platform_is_not :windows do +platform_is_not :windows do + describe "File.lutime" do + it_behaves_like :update_time, :lutime + end + + describe "File.lutime" do before :each do @atime = Time.utc(2000) @mtime = Time.utc(2001) diff --git a/spec/ruby/core/file/shared/update_time.rb b/spec/ruby/core/file/shared/update_time.rb new file mode 100644 index 00000000000000..9c063a8e935484 --- /dev/null +++ b/spec/ruby/core/file/shared/update_time.rb @@ -0,0 +1,105 @@ +describe :update_time, shared: true do + before :all do + @time_is_float = platform_is :windows + end + + before :each do + @atime = Time.now + @mtime = Time.now + @file1 = tmp("specs_file_utime1") + @file2 = tmp("specs_file_utime2") + touch @file1 + touch @file2 + end + + after :each do + rm_r @file1, @file2 + end + + it "sets the access and modification time of each file" do + File.send(@method, @atime, @mtime, @file1, @file2) + + if @time_is_float + File.atime(@file1).should be_close(@atime, 0.0001) + File.mtime(@file1).should be_close(@mtime, 0.0001) + File.atime(@file2).should be_close(@atime, 0.0001) + File.mtime(@file2).should be_close(@mtime, 0.0001) + else + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + end + end + + it "uses the current times if two nil values are passed" do + tn = Time.now + File.send(@method, nil, nil, @file1, @file2) + + if @time_is_float + File.atime(@file1).should be_close(tn, 0.050) + File.mtime(@file1).should be_close(tn, 0.050) + File.atime(@file2).should be_close(tn, 0.050) + File.mtime(@file2).should be_close(tn, 0.050) + else + File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) + end + end + + it "accepts an object that has a #to_path method" do + File.send(@method, @atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) + end + + it "accepts numeric atime and mtime arguments" do + if @time_is_float + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2) + + File.atime(@file1).should be_close(@atime, 0.0001) + File.mtime(@file1).should be_close(@mtime, 0.0001) + File.atime(@file2).should be_close(@atime, 0.0001) + File.mtime(@file2).should be_close(@mtime, 0.0001) + else + File.send(@method, @atime.to_i, @mtime.to_i, @file1, @file2) + + File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) + File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) + end + end + + it "may set nanosecond precision" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) + File.send(@method, t, t, @file1) + + File.atime(@file1).nsec.should.between?(0, 123500000) + File.mtime(@file1).nsec.should.between?(0, 123500000) + end + + it "returns the number of filenames in the arguments" do + File.send(@method, @atime.to_f, @mtime.to_f, @file1, @file2).should == 2 + end + + platform_is :linux do + platform_is wordsize: 64 do + it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do + # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps + # "Therefore, timestamps should not overflow until May 2446." + # https://lwn.net/Articles/804382/ + # "On-disk timestamps hitting the y2038 limit..." + # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8 + # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz + # Amazon Linux 2023 returns 2486-07-02 in this example + # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz + time = Time.at(1<<44) + File.send(@method, time, time, @file1) + + [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year + [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year + end + end + end +end diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb index 0b0e4f979c9356..d87626be509458 100644 --- a/spec/ruby/core/file/utime_spec.rb +++ b/spec/ruby/core/file/utime_spec.rb @@ -1,102 +1,6 @@ require_relative '../../spec_helper' +require_relative 'shared/update_time' describe "File.utime" do - - before :all do - @time_is_float = platform_is :windows - end - - before :each do - @atime = Time.now - @mtime = Time.now - @file1 = tmp("specs_file_utime1") - @file2 = tmp("specs_file_utime2") - touch @file1 - touch @file2 - end - - after :each do - rm_r @file1, @file2 - end - - it "sets the access and modification time of each file" do - File.utime(@atime, @mtime, @file1, @file2) - if @time_is_float - File.atime(@file1).should be_close(@atime, 0.0001) - File.mtime(@file1).should be_close(@mtime, 0.0001) - File.atime(@file2).should be_close(@atime, 0.0001) - File.mtime(@file2).should be_close(@mtime, 0.0001) - else - File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) - File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) - File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) - File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) - end - end - - it "uses the current times if two nil values are passed" do - tn = Time.now - File.utime(nil, nil, @file1, @file2) - if @time_is_float - File.atime(@file1).should be_close(tn, 0.050) - File.mtime(@file1).should be_close(tn, 0.050) - File.atime(@file2).should be_close(tn, 0.050) - File.mtime(@file2).should be_close(tn, 0.050) - else - File.atime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) - File.mtime(@file1).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) - File.atime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) - File.mtime(@file2).to_i.should be_close(Time.now.to_i, TIME_TOLERANCE) - end - end - - it "accepts an object that has a #to_path method" do - File.utime(@atime, @mtime, mock_to_path(@file1), mock_to_path(@file2)) - end - - it "accepts numeric atime and mtime arguments" do - if @time_is_float - File.utime(@atime.to_f, @mtime.to_f, @file1, @file2) - File.atime(@file1).should be_close(@atime, 0.0001) - File.mtime(@file1).should be_close(@mtime, 0.0001) - File.atime(@file2).should be_close(@atime, 0.0001) - File.mtime(@file2).should be_close(@mtime, 0.0001) - else - File.utime(@atime.to_i, @mtime.to_i, @file1, @file2) - File.atime(@file1).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) - File.mtime(@file1).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) - File.atime(@file2).to_i.should be_close(@atime.to_i, TIME_TOLERANCE) - File.mtime(@file2).to_i.should be_close(@mtime.to_i, TIME_TOLERANCE) - end - end - - it "may set nanosecond precision" do - t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) - File.utime(t, t, @file1) - File.atime(@file1).nsec.should.between?(0, 123500000) - File.mtime(@file1).nsec.should.between?(0, 123500000) - end - - it "returns the number of filenames in the arguments" do - File.utime(@atime.to_f, @mtime.to_f, @file1, @file2).should == 2 - end - - platform_is :linux do - platform_is wordsize: 64 do - it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19 or 2486-07-02)" do - # https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps - # "Therefore, timestamps should not overflow until May 2446." - # https://lwn.net/Articles/804382/ - # "On-disk timestamps hitting the y2038 limit..." - # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8 - # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz - # Amazon Linux 2023 returns 2486-07-02 in this example - # http://rubyci.s3.amazonaws.com/amazon2023/ruby-master/log/20230322T063004Z.fail.html.gz - time = Time.at(1<<44) - File.utime(time, time, @file1) - [559444, 2486, 2446, 2038].should.include? File.atime(@file1).year - [559444, 2486, 2446, 2038].should.include? File.mtime(@file1).year - end - end - end + it_behaves_like :update_time, :utime end diff --git a/spec/ruby/core/filetest/exist_spec.rb b/spec/ruby/core/filetest/exist_spec.rb index 4d14bea2311738..a95d3f91a18d96 100644 --- a/spec/ruby/core/filetest/exist_spec.rb +++ b/spec/ruby/core/filetest/exist_spec.rb @@ -4,3 +4,11 @@ describe "FileTest.exist?" do it_behaves_like :file_exist, :exist?, FileTest end + +ruby_version_is "3.2" do + describe "FileTest.exists?" do + it "has been removed" do + FileTest.should_not.respond_to?(:exists?) + end + end +end diff --git a/spec/ruby/core/kernel/not_match_spec.rb b/spec/ruby/core/kernel/not_match_spec.rb index 906f18df2c66e1..f8dd82fad86543 100644 --- a/spec/ruby/core/kernel/not_match_spec.rb +++ b/spec/ruby/core/kernel/not_match_spec.rb @@ -14,6 +14,20 @@ def !~(obj) (obj !~ :foo).should == false end + ruby_version_is ""..."3.2" do + it "returns true if self does not respond to #=~" do + suppress_warning do + (Object.new !~ :foo).should == true + end + end + end + + ruby_version_is "3.2" do + it "raises NoMethodError if self does not respond to #=~" do + -> { Object.new !~ :foo }.should raise_error(NoMethodError) + end + end + it 'can be overridden in subclasses' do obj = KernelSpecs::NotMatch.new (obj !~ :bar).should == :foo diff --git a/spec/ruby/core/method/parameters_spec.rb b/spec/ruby/core/method/parameters_spec.rb index 7d2b37fac75194..8495aef4d2d32d 100644 --- a/spec/ruby/core/method/parameters_spec.rb +++ b/spec/ruby/core/method/parameters_spec.rb @@ -22,6 +22,8 @@ def one_splat_one_block(*args, &block) local_is_not_parameter = {} end + def forward_parameters(...) end + def underscore_parameters(_, _, _ = 1, *_, _:, _: 2, **_, &_); end define_method(:one_optional_defined_method) {|x = 1|} @@ -267,6 +269,20 @@ def object.foo(&) end end + ruby_version_is ""..."3.1" do + it "returns [:rest, :*], [:block, :&] for forward parameters operator" do + m = MethodSpecs::Methods.new + m.method(:forward_parameters).parameters.should == [[:rest, :*], [:block, :&]] + end + end + + ruby_version_is "3.1" do + it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do + m = MethodSpecs::Methods.new + m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]] + end + end + it "returns the args and block for a splat and block argument" do m = MethodSpecs::Methods.new m.method(:one_splat_one_block).parameters.should == [[:rest, :args], [:block, :block]] diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb index 6c21784ab65d9d..972596d2ea8809 100644 --- a/spec/ruby/core/proc/parameters_spec.rb +++ b/spec/ruby/core/proc/parameters_spec.rb @@ -33,6 +33,16 @@ it "regards named parameters in lambda as optional if lambda: false keyword used" do -> x { }.parameters(lambda: false).first.first.should == :opt end + + it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do + proc {|x| }.parameters(lambda: 123).first.first.should == :req + -> x { }.parameters(lambda: 123).first.first.should == :req + end + + it "ignores the lambda keyword if it is nil" do + proc {|x|}.parameters(lambda: nil).first.first.should == :opt + -> x { }.parameters(lambda: nil).first.first.should == :req + end end it "regards optional keyword parameters in procs as optional" do @@ -160,4 +170,8 @@ [:block, :_] ] end + + it "returns :nokey for **nil parameter" do + proc { |**nil| }.parameters.should == [[:nokey]] + end end diff --git a/spec/ruby/core/string/to_i_spec.rb b/spec/ruby/core/string/to_i_spec.rb index e4fa89aab3e268..9931502baa2459 100644 --- a/spec/ruby/core/string/to_i_spec.rb +++ b/spec/ruby/core/string/to_i_spec.rb @@ -10,6 +10,18 @@ "1_2_3asdf".to_i.should == 123 end + it "ignores multiple non-consecutive underscoes when the first digit is 0" do + (2..16).each do |base| + "0_0_010".to_i(base).should == base; + end + end + + it "bails out at the first double underscore if the first digit is 0" do + (2..16).each do |base| + "010__1".to_i(base).should == base; + end + end + it "ignores leading whitespaces" do [ " 123", " 123", "\r\n\r\n123", "\t\t123", "\r\n\t\n123", " \t\n\r\t 123"].each do |str| diff --git a/spec/ruby/library/net-ftp/connect_spec.rb b/spec/ruby/library/net-ftp/connect_spec.rb index b5060bd1ca744c..4330d430b47c8d 100644 --- a/spec/ruby/library/net-ftp/connect_spec.rb +++ b/spec/ruby/library/net-ftp/connect_spec.rb @@ -29,7 +29,7 @@ ruby_version_is ""..."3.1" do it "prints a small debug line when in debug mode" do @ftp.debug_mode = true - -> { @ftp.connect(@server.hostname, @server.server_port) }.should output(/#{"connect: "}#{@server.hostname}#{", "}#{@server.server_port}#{"\\nget: 220 Dummy FTP Server ready!"}/) + -> { @ftp.connect(@server.hostname, @server.server_port) }.should output(/connect: #{@server.hostname}, #{@server.server_port}\nget: 220 Dummy FTP Server ready!/) @ftp.debug_mode = false end end diff --git a/spec/ruby/library/set/set_spec.rb b/spec/ruby/library/set/set_spec.rb new file mode 100644 index 00000000000000..2a4edc6dfc63b4 --- /dev/null +++ b/spec/ruby/library/set/set_spec.rb @@ -0,0 +1,12 @@ +require_relative '../../spec_helper' + +describe 'Set' do + ruby_version_is '3.2' do + it 'is available without explicit requiring' do + output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1') + puts Set.new([1, 2, 3]) + RUBY + output.chomp.should == "#" + end + end +end diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb index 36437cc7b683b5..b0c38d75a93538 100644 --- a/spec/ruby/optional/capi/encoding_spec.rb +++ b/spec/ruby/optional/capi/encoding_spec.rb @@ -2,7 +2,7 @@ require_relative 'spec_helper' require_relative 'fixtures/encoding' -load_extension('encoding') +extension_path = load_extension('encoding') describe :rb_enc_get_index, shared: true do it "returns the index of the encoding of a String" do @@ -559,19 +559,19 @@ describe "rb_ascii8bit_encindex" do it "returns an index for the ASCII-8BIT encoding" do - @s.rb_ascii8bit_encindex().should >= 0 + @s.rb_ascii8bit_encindex().should == 0 end end describe "rb_utf8_encindex" do it "returns an index for the UTF-8 encoding" do - @s.rb_utf8_encindex().should >= 0 + @s.rb_utf8_encindex().should == 1 end end describe "rb_usascii_encindex" do it "returns an index for the US-ASCII encoding" do - @s.rb_usascii_encindex().should >= 0 + @s.rb_usascii_encindex().should == 2 end end @@ -721,4 +721,27 @@ str.bytes.should == [0, 0x24] end end + + describe "rb_define_dummy_encoding" do + it "defines the dummy encoding" do + @s.rb_define_dummy_encoding("FOO") + enc = Encoding.find("FOO") + enc.should.dummy? + end + + it "returns the index of the dummy encoding" do + index = @s.rb_define_dummy_encoding("BAR") + index.should == Encoding.list.size - 1 + end + + ruby_version_is "3.2" do + it "raises EncodingError if too many encodings" do + code = <<-RUBY + require #{extension_path.dump} + 1_000.times {|i| CApiEncodingSpecs.new.rb_define_dummy_encoding("R_\#{i}") } + RUBY + ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)') + end + end + end end diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c index 3343848b542958..aa8662cfbd6426 100644 --- a/spec/ruby/optional/capi/ext/encoding_spec.c +++ b/spec/ruby/optional/capi/ext/encoding_spec.c @@ -320,6 +320,10 @@ static VALUE encoding_spec_rb_enc_left_char_head(VALUE self, VALUE str, VALUE of return LONG2NUM(result - ptr); } +static VALUE encoding_spec_rb_define_dummy_encoding(VALUE self, VALUE name) { + return INT2NUM(rb_define_dummy_encoding(RSTRING_PTR(name))); +} + void Init_encoding_spec(void) { VALUE cls; native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*)); @@ -379,6 +383,7 @@ void Init_encoding_spec(void) { rb_define_method(cls, "rb_uv_to_utf8", encoding_spec_rb_uv_to_utf8, 2); rb_define_method(cls, "ONIGENC_MBC_CASE_FOLD", encoding_spec_ONIGENC_MBC_CASE_FOLD, 1); rb_define_method(cls, "rb_enc_left_char_head", encoding_spec_rb_enc_left_char_head, 2); + rb_define_method(cls, "rb_define_dummy_encoding", encoding_spec_rb_define_dummy_encoding, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index c9c5277732ecbf..070a88759ba297 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -51,10 +51,6 @@ VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) { return INT2FIX(RSTRING_LEN(str)); } -VALUE string_spec_rb_str_fstring(VALUE self, VALUE str) { - return rb_str_to_interned_str(str); -} - VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) { VALUE buf; @@ -576,11 +572,19 @@ static VALUE string_spec_rb_str_unlocktmp(VALUE self, VALUE str) { return rb_str_unlocktmp(str); } +static VALUE string_spec_rb_enc_interned_str_cstr(VALUE self, VALUE str, VALUE enc) { + rb_encoding *e = rb_to_encoding(enc); + return rb_enc_interned_str_cstr(RSTRING_PTR(str), e); +} + +static VALUE string_spec_rb_str_to_interned_str(VALUE self, VALUE str) { + return rb_str_to_interned_str(str); +} + void Init_string_spec(void) { VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject); rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2); rb_define_method(cls, "rb_cstr_to_inum", string_spec_rb_cstr_to_inum, 3); - rb_define_method(cls, "rb_fstring", string_spec_rb_str_fstring, 1); rb_define_method(cls, "rb_str2inum", string_spec_rb_str2inum, 2); rb_define_method(cls, "rb_str_append", string_spec_rb_str_append, 2); rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2); @@ -677,6 +681,8 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_catf", string_spec_rb_str_catf, 1); rb_define_method(cls, "rb_str_locktmp", string_spec_rb_str_locktmp, 1); rb_define_method(cls, "rb_str_unlocktmp", string_spec_rb_str_unlocktmp, 1); + rb_define_method(cls, "rb_enc_interned_str_cstr", string_spec_rb_enc_interned_str_cstr, 2); + rb_define_method(cls, "rb_str_to_interned_str", string_spec_rb_str_to_interned_str, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb index 3a47fa9762fddc..d9c20cf1760ff9 100644 --- a/spec/ruby/optional/capi/string_spec.rb +++ b/spec/ruby/optional/capi/string_spec.rb @@ -498,25 +498,6 @@ def inspect end end - describe "rb_fstring" do - it 'returns self if the String is frozen' do - input = 'foo'.freeze - output = @s.rb_fstring(input) - - output.should equal(input) - output.should.frozen? - end - - it 'returns a frozen copy if the String is not frozen' do - input = 'foo' - output = @s.rb_fstring(input) - - output.should.frozen? - output.should_not equal(input) - output.should == 'foo' - end - end - describe "rb_str_subseq" do it "returns a byte-indexed substring" do str = "\x00\x01\x02\x03\x04".force_encoding("binary") @@ -1227,4 +1208,59 @@ def inspect -> { @s.rb_str_unlocktmp("test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string') end end + + describe "rb_enc_interned_str_cstr" do + it "returns a frozen string" do + str = "hello" + val = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII) + + val.should.is_a?(String) + val.encoding.should == Encoding::US_ASCII + val.should.frozen? + end + + it "returns the same frozen string" do + str = "hello" + result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII) + result2 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII) + result1.should.equal?(result2) + end + + it "returns different frozen strings for different encodings" do + str = "hello" + result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII) + result2 = @s.rb_enc_interned_str_cstr(str, Encoding::UTF_8) + result1.should_not.equal?(result2) + end + + it "returns the same string as String#-@" do + @s.rb_enc_interned_str_cstr("hello", Encoding::UTF_8).should.equal?(-"hello") + end + end + + describe "rb_str_to_interned_str" do + it "returns a frozen string" do + str = "hello" + result = @s.rb_str_to_interned_str(str) + result.should.is_a?(String) + result.should.frozen? + end + + it "returns the same frozen string" do + str = "hello" + result1 = @s.rb_str_to_interned_str(str) + result2 = @s.rb_str_to_interned_str(str) + result1.should.equal?(result2) + end + + it "returns different frozen strings for different encodings" do + result1 = @s.rb_str_to_interned_str("hello".force_encoding(Encoding::US_ASCII)) + result2 = @s.rb_str_to_interned_str("hello".force_encoding(Encoding::UTF_8)) + result1.should_not.equal?(result2) + end + + it "returns the same string as String#-@" do + @s.rb_str_to_interned_str("hello").should.equal?(-"hello") + end + end end From 1a57fee7af872a4efa94ba0e8f350c6ee6617f80 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 08:46:12 -0500 Subject: [PATCH 092/147] [ruby/prism] Fix multi write with modifier rescue https://github.com/ruby/prism/commit/8ea7a3270f --- prism/prism.c | 14 +++-- test/prism/fixtures/multi_write.txt | 4 ++ test/prism/ruby_parser_test.rb | 1 + test/prism/snapshots/multi_write.txt | 93 ++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 test/prism/fixtures/multi_write.txt create mode 100644 test/prism/snapshots/multi_write.txt diff --git a/prism/prism.c b/prism/prism.c index 864dd49f511b3d..fecc25336dba9f 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17051,10 +17051,10 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ static inline pm_node_t * parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id); + bool single_value = true; - bool is_single_value = true; if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { - is_single_value = false; + single_value = false; pm_token_t opening = not_provided(parser); pm_array_node_t *array = pm_array_node_create(parser, &opening); @@ -17068,16 +17068,18 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - // Contradicting binding powers, the right-hand-side value of the assignment allows the `rescue` modifier. - if (is_single_value && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { + // Contradicting binding powers, the right-hand-side value of the assignment + // allows the `rescue` modifier. + if ((single_value || (binding_power == (PM_BINDING_POWER_MULTI_ASSIGNMENT + 1))) && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { pm_token_t rescue = parser->current; parser_lex(parser); bool accepts_command_call_inner = false; - // RHS can accept command call iff the value is a call with arguments but without paranthesis. + // RHS can accept command call iff the value is a call with arguments + // but without paranthesis. if (PM_NODE_TYPE_P(value, PM_CALL_NODE)) { - pm_call_node_t *call_node = (pm_call_node_t *)value; + pm_call_node_t *call_node = (pm_call_node_t *) value; if ((call_node->arguments != NULL) && (call_node->opening_loc.start == NULL)) { accepts_command_call_inner = true; } diff --git a/test/prism/fixtures/multi_write.txt b/test/prism/fixtures/multi_write.txt new file mode 100644 index 00000000000000..edbcafb969772a --- /dev/null +++ b/test/prism/fixtures/multi_write.txt @@ -0,0 +1,4 @@ +foo = 1 rescue nil +foo, bar = 1 rescue nil +foo = 1, 2 rescue nil +foo, bar = 1, 2 rescue nil diff --git a/test/prism/ruby_parser_test.rb b/test/prism/ruby_parser_test.rb index a71d05e78cb75b..89150b2faac33e 100644 --- a/test/prism/ruby_parser_test.rb +++ b/test/prism/ruby_parser_test.rb @@ -73,6 +73,7 @@ class RubyParserTest < TestCase alias.txt method_calls.txt methods.txt + multi_write.txt not.txt patterns.txt regex.txt diff --git a/test/prism/snapshots/multi_write.txt b/test/prism/snapshots/multi_write.txt new file mode 100644 index 00000000000000..d313801fdb2b89 --- /dev/null +++ b/test/prism/snapshots/multi_write.txt @@ -0,0 +1,93 @@ +@ ProgramNode (location: (1,0)-(4,26)) +├── locals: [:foo, :bar] +└── statements: + @ StatementsNode (location: (1,0)-(4,26)) + └── body: (length: 4) + ├── @ LocalVariableWriteNode (location: (1,0)-(1,18)) + │ ├── name: :foo + │ ├── depth: 0 + │ ├── name_loc: (1,0)-(1,3) = "foo" + │ ├── value: + │ │ @ RescueModifierNode (location: (1,6)-(1,18)) + │ │ ├── expression: + │ │ │ @ IntegerNode (location: (1,6)-(1,7)) + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 + │ │ ├── keyword_loc: (1,8)-(1,14) = "rescue" + │ │ └── rescue_expression: + │ │ @ NilNode (location: (1,15)-(1,18)) + │ └── operator_loc: (1,4)-(1,5) = "=" + ├── @ MultiWriteNode (location: (2,0)-(2,23)) + │ ├── lefts: (length: 2) + │ │ ├── @ LocalVariableTargetNode (location: (2,0)-(2,3)) + │ │ │ ├── name: :foo + │ │ │ └── depth: 0 + │ │ └── @ LocalVariableTargetNode (location: (2,5)-(2,8)) + │ │ ├── name: :bar + │ │ └── depth: 0 + │ ├── rest: ∅ + │ ├── rights: (length: 0) + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── operator_loc: (2,9)-(2,10) = "=" + │ └── value: + │ @ RescueModifierNode (location: (2,11)-(2,23)) + │ ├── expression: + │ │ @ IntegerNode (location: (2,11)-(2,12)) + │ │ ├── flags: decimal + │ │ └── value: 1 + │ ├── keyword_loc: (2,13)-(2,19) = "rescue" + │ └── rescue_expression: + │ @ NilNode (location: (2,20)-(2,23)) + ├── @ RescueModifierNode (location: (3,0)-(3,21)) + │ ├── expression: + │ │ @ LocalVariableWriteNode (location: (3,0)-(3,10)) + │ │ ├── name: :foo + │ │ ├── depth: 0 + │ │ ├── name_loc: (3,0)-(3,3) = "foo" + │ │ ├── value: + │ │ │ @ ArrayNode (location: (3,6)-(3,10)) + │ │ │ ├── flags: ∅ + │ │ │ ├── elements: (length: 2) + │ │ │ │ ├── @ IntegerNode (location: (3,6)-(3,7)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 + │ │ │ │ └── @ IntegerNode (location: (3,9)-(3,10)) + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 + │ │ │ ├── opening_loc: ∅ + │ │ │ └── closing_loc: ∅ + │ │ └── operator_loc: (3,4)-(3,5) = "=" + │ ├── keyword_loc: (3,11)-(3,17) = "rescue" + │ └── rescue_expression: + │ @ NilNode (location: (3,18)-(3,21)) + └── @ MultiWriteNode (location: (4,0)-(4,26)) + ├── lefts: (length: 2) + │ ├── @ LocalVariableTargetNode (location: (4,0)-(4,3)) + │ │ ├── name: :foo + │ │ └── depth: 0 + │ └── @ LocalVariableTargetNode (location: (4,5)-(4,8)) + │ ├── name: :bar + │ └── depth: 0 + ├── rest: ∅ + ├── rights: (length: 0) + ├── lparen_loc: ∅ + ├── rparen_loc: ∅ + ├── operator_loc: (4,9)-(4,10) = "=" + └── value: + @ RescueModifierNode (location: (4,11)-(4,26)) + ├── expression: + │ @ ArrayNode (location: (4,11)-(4,15)) + │ ├── flags: ∅ + │ ├── elements: (length: 2) + │ │ ├── @ IntegerNode (location: (4,11)-(4,12)) + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 + │ │ └── @ IntegerNode (location: (4,14)-(4,15)) + │ │ ├── flags: decimal + │ │ └── value: 2 + │ ├── opening_loc: ∅ + │ └── closing_loc: ∅ + ├── keyword_loc: (4,16)-(4,22) = "rescue" + └── rescue_expression: + @ NilNode (location: (4,23)-(4,26)) From 83e676e5f9049168047c36d1bbd75ac342e6fed6 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 23 Feb 2024 13:50:46 -0500 Subject: [PATCH 093/147] Don't lookup finalizers if FL_FINALIZE flag not set The FL_FINALIZE flag is set when there are finalizers for the object. We can improver performance by not looking up in the table if the flag is not set. Using the following C extension: #include "ruby/ruby.h" static void data_free(void *_ptr) {} static const rb_data_type_t data_type = { "my_type", { NULL, data_free, }, 0, 0, 0 }; static VALUE data_alloc(VALUE klass) { return TypedData_Wrap_Struct(klass, &data_type, (void *)1); } void Init_myext(void) { VALUE my_klass = rb_define_class("MyClass", rb_cObject); rb_define_alloc_func(my_klass, data_alloc); } And the following benchmark: require "benchmark" final_objs = 1_000_000.times.map do o = Object.new ObjectSpace.define_finalizer(o, proc {}) o end puts(Benchmark.measure do 100_000_000.times do MyClass.new end end) Before: 10.974190 0.355037 11.329227 ( 11.416772) After: 7.664310 0.347598 8.011908 ( 8.268969) --- gc.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/gc.c b/gc.c index c6e0752a3e6178..cec6c94334286a 100644 --- a/gc.c +++ b/gc.c @@ -3143,7 +3143,7 @@ static inline void make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data) { struct RZombie *zombie = RZOMBIE(obj); - zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & FL_SEEN_OBJ_ID); + zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & (FL_SEEN_OBJ_ID | FL_FINALIZE)); zombie->dfree = dfree; zombie->data = data; VALUE prev, next = heap_pages_deferred_final; @@ -4115,15 +4115,22 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) static void run_final(rb_objspace_t *objspace, VALUE zombie) { - st_data_t key, table; - if (RZOMBIE(zombie)->dfree) { RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data); } - key = (st_data_t)zombie; - if (st_delete(finalizer_table, &key, &table)) { - run_finalizer(objspace, zombie, (VALUE)table); + st_data_t key = (st_data_t)zombie; + if (FL_TEST_RAW(zombie, FL_FINALIZE)) { + st_data_t table; + if (st_delete(finalizer_table, &key, &table)) { + run_finalizer(objspace, zombie, (VALUE)table); + } + else { + rb_bug("FL_FINALIZE flag is set, but finalizers are not found"); + } + } + else { + GC_ASSERT(!st_lookup(finalizer_table, key, NULL)); } } @@ -4299,9 +4306,12 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) st_foreach(finalizer_table, force_chain_object, (st_data_t)&list); while (list) { struct force_finalize_list *curr = list; - st_data_t obj = (st_data_t)curr->obj; run_finalizer(objspace, curr->obj, curr->table); + FL_UNSET(curr->obj, FL_FINALIZE); + + st_data_t obj = (st_data_t)curr->obj; st_delete(finalizer_table, &obj, 0); + list = curr->next; xfree(curr); } From af3145bb2446f27f895e78cfab49eea23fad8865 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 09:18:17 -0500 Subject: [PATCH 094/147] [ruby/prism] Handle negated numeric in parser translation https://github.com/ruby/prism/commit/5877a95be4 --- lib/prism/translation/parser/compiler.rb | 39 ++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 423df8fb8c2c55..c8ab3740bdeb17 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -247,6 +247,11 @@ def visit_call_node(node) if node.call_operator_loc.nil? case name + when :-@ + case (receiver = node.receiver).type + when :integer_node, :float_node, :rational_node, :imaginary_node + return visit(numeric_negate(node.message_loc, receiver)) + end when :! return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block) when :[] @@ -792,7 +797,7 @@ def visit_if_node(node) # 1i def visit_imaginary_node(node) - visit_numeric(node, builder.complex([node.value, srange(node.location)])) + visit_numeric(node, builder.complex([imaginary_value(node), srange(node.location)])) end # { foo: } @@ -1325,7 +1330,7 @@ def visit_range_node(node) # 1r # ^^ def visit_rational_node(node) - visit_numeric(node, builder.rational([node.value, srange(node.location)])) + visit_numeric(node, builder.rational([rational_value(node), srange(node.location)])) end # redo @@ -1690,6 +1695,26 @@ def find_forwarding(node) forwarding end + # Because we have mutated the AST to allow for newlines in the middle of + # a rational, we need to manually handle the value here. + def imaginary_value(node) + Complex(0, node.numeric.is_a?(RationalNode) ? rational_value(node.numeric) : node.numeric.value) + end + + # Negate the value of a numeric node. This is a special case where you + # have a negative sign on one line and then a number on the next line. + # In normal Ruby, this will always be a method call. The parser gem, + # however, marks this as a numeric literal. We have to massage the tree + # here to get it into the correct form. + def numeric_negate(message_loc, receiver) + case receiver.type + when :integer_node, :float_node + receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location)) + when :rational_node, :imaginary_node + receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location)) + end + end + # Blocks can have a special set of parameters that automatically expand # when given arrays if they have a single required parameter and no # other parameters. @@ -1704,6 +1729,16 @@ def procarg0?(parameters) parameters.block.nil? end + # Because we have mutated the AST to allow for newlines in the middle of + # a rational, we need to manually handle the value here. + def rational_value(node) + if node.numeric.is_a?(IntegerNode) + Rational(node.numeric.value) + else + Rational(node.slice.gsub(/\s/, "").chomp("r")) + end + end + # Locations in the parser gem AST are generated using this class. We # store a reference to its constant to make it slightly faster to look # up. From 99d0f687fc4928e06196a695e553acb029d17b61 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 09:26:31 -0500 Subject: [PATCH 095/147] [ruby/prism] Fix parser translator for pinned expression https://github.com/ruby/prism/commit/eeae07193b --- lib/prism/translation/parser/compiler.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index c8ab3740bdeb17..4edbae217d673a 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -1271,7 +1271,8 @@ def visit_parentheses_node(node) # foo => ^(bar) # ^^^^^^ def visit_pinned_expression_node(node) - builder.pin(token(node.operator_loc), visit(node.expression)) + expression = builder.begin(token(node.lparen_loc), visit(node.expression), token(node.rparen_loc)) + builder.pin(token(node.operator_loc), expression) end # foo = 1 and bar => ^foo From 1ce3d9acbf59415f18a2d0ddf4a846cedf17a375 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 09:35:52 -0500 Subject: [PATCH 096/147] [ruby/prism] Fix xstring heredoc parser translator https://github.com/ruby/prism/commit/4e0f703975 --- lib/prism/node_ext.rb | 24 ++++++++++++++++++++++++ lib/prism/translation/parser/compiler.rb | 12 ++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index fdd6ac200d229d..4ec7c3014cb464 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -49,10 +49,34 @@ class InterpolatedXStringNode < Node class StringNode < Node include HeredocQuery + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + def to_interpolated + InterpolatedStringNode.new( + source, + opening_loc, + [copy(opening_loc: nil, closing_loc: nil, location: content_loc)], + closing_loc, + location + ) + end end class XStringNode < Node include HeredocQuery + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + def to_interpolated + InterpolatedXStringNode.new( + source, + opening_loc, + [StringNode.new(source, 0, nil, content_loc, nil, unescaped, content_loc)], + closing_loc, + location + ) + end end private_constant :HeredocQuery diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index 4edbae217d673a..ab6cea9484f51c 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -942,7 +942,7 @@ def visit_interpolated_regular_expression_node(node) # "foo #{bar}" # ^^^^^^^^^^^^ def visit_interpolated_string_node(node) - if node.opening&.start_with?("<<") + if node.heredoc? children, closing = visit_heredoc(node) builder.string_compose(token(node.opening_loc), children, closing) else @@ -967,7 +967,7 @@ def visit_interpolated_symbol_node(node) # `foo #{bar}` # ^^^^^^^^^^^^ def visit_interpolated_x_string_node(node) - if node.opening.start_with?("<<") + if node.heredoc? children, closing = visit_heredoc(node) builder.xstring_compose(token(node.opening_loc), children, closing) else @@ -1485,8 +1485,8 @@ def visit_statements_node(node) # "foo" # ^^^^^ def visit_string_node(node) - if node.opening&.start_with?("<<") - children, closing = visit_heredoc(InterpolatedStringNode.new(node.send(:source), node.opening_loc, [node.copy(opening_loc: nil, closing_loc: nil, location: node.content_loc)], node.closing_loc, node.location)) + if node.heredoc? + children, closing = visit_heredoc(node.to_interpolated) builder.string_compose(token(node.opening_loc), children, closing) elsif node.opening == "?" builder.character([node.unescaped, srange(node.location)]) @@ -1646,8 +1646,8 @@ def visit_while_node(node) # `foo` # ^^^^^ def visit_x_string_node(node) - if node.opening&.start_with?("<<") - children, closing = visit_heredoc(InterpolatedXStringNode.new(node.opening_loc, [StringNode.new(0, nil, node.content_loc, nil, node.unescaped, node.content_loc)], node.closing_loc, node.location)) + if node.heredoc? + children, closing = visit_heredoc(node.to_interpolated) builder.xstring_compose(token(node.opening_loc), children, closing) else builder.xstring_compose( From 27e3e44390cf83f1c11f33c0f73c5034a675ccea Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:38:44 -0500 Subject: [PATCH 097/147] Fix verify_internal_consistency_i for zombie objects FL_FINALIZE is now kept for zombie objects. --- gc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gc.c b/gc.c index cec6c94334286a..a2b8589e4b686e 100644 --- a/gc.c +++ b/gc.c @@ -3139,11 +3139,13 @@ cvar_table_free_i(VALUE value, void *ctx) return ID_TABLE_CONTINUE; } +#define ZOMBIE_OBJ_KEPT_FLAGS (FL_SEEN_OBJ_ID | FL_FINALIZE) + static inline void make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data) { struct RZombie *zombie = RZOMBIE(obj); - zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & (FL_SEEN_OBJ_ID | FL_FINALIZE)); + zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & ZOMBIE_OBJ_KEPT_FLAGS); zombie->dfree = dfree; zombie->data = data; VALUE prev, next = heap_pages_deferred_final; @@ -7587,7 +7589,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, } else { if (BUILTIN_TYPE(obj) == T_ZOMBIE) { - GC_ASSERT((RBASIC(obj)->flags & ~FL_SEEN_OBJ_ID) == T_ZOMBIE); + GC_ASSERT((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) == T_ZOMBIE); data->zombie_object_count++; } } From 9c5a91e32042939d6325452b04b02000a215afcb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:52:19 +0000 Subject: [PATCH 098/147] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.88 to 0.9.89. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.88...v0.9.89) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/94e6907098 --- .../rust_ruby_example/Cargo.lock | 8 ++++---- .../rust_ruby_example/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index c5887f0369f088..56ed78e61a7d85 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -145,18 +145,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.88" +version = "0.9.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11b0965e6df9ef800ac71efc46070960a119f92af1b64d6acd4c357dc139350" +checksum = "0d197f2c03751ef006f29d593d22aa9068c9c358e04ca503afea0329c366147c" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.88" +version = "0.9.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0fce6e53552df8fcd3e4269d7944b0afa38db70d252bbf12caad454caf6d83" +checksum = "2b50caf8fd028f12abe00d6debe2ae2adf6202c9ca3caa59487eda710d90fa28" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml index b2a2b239bb6265..c0cbae00c5a2b4 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.88" +rb-sys = "0.9.89" From f54122368c372b5ba72ef04a315e3549cbddf9d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:11:05 +0000 Subject: [PATCH 099/147] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.88 to 0.9.89. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.88...v0.9.89) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/75e5ec62be --- .../custom_name/ext/custom_name_lib/Cargo.lock | 8 ++++---- .../custom_name/ext/custom_name_lib/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index a220eef78893d7..ed0ce757331a50 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -152,18 +152,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.88" +version = "0.9.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11b0965e6df9ef800ac71efc46070960a119f92af1b64d6acd4c357dc139350" +checksum = "0d197f2c03751ef006f29d593d22aa9068c9c358e04ca503afea0329c366147c" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.88" +version = "0.9.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0fce6e53552df8fcd3e4269d7944b0afa38db70d252bbf12caad454caf6d83" +checksum = "2b50caf8fd028f12abe00d6debe2ae2adf6202c9ca3caa59487eda710d90fa28" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml index e104f1c07ec67b..e2c72480c1b604 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.88" +rb-sys = "0.9.89" From 34bad6d69f7a7fa10a4e5aa48a6895afc9aebf1e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 12:45:42 -0500 Subject: [PATCH 100/147] [ruby/prism] Triple-check prism encodings https://github.com/ruby/prism/commit/ab7f261354 --- prism/encoding.c | 137 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 101 insertions(+), 36 deletions(-) diff --git a/prism/encoding.c b/prism/encoding.c index 1d455c242127bd..dc63cccc2db2a4 100644 --- a/prism/encoding.c +++ b/prism/encoding.c @@ -1499,7 +1499,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP 0x31350, 0x323AF, }; -#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1296 +#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1302 static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS_LENGTH] = { 0x100, 0x100, 0x102, 0x102, @@ -1582,9 +1582,9 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C 0x1B5, 0x1B5, 0x1B7, 0x1B8, 0x1BC, 0x1BC, - 0x1C4, 0x1C4, - 0x1C7, 0x1C7, - 0x1CA, 0x1CA, + 0x1C4, 0x1C5, + 0x1C7, 0x1C8, + 0x1CA, 0x1CB, 0x1CD, 0x1CD, 0x1CF, 0x1CF, 0x1D1, 0x1D1, @@ -1602,7 +1602,7 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C 0x1EA, 0x1EA, 0x1EC, 0x1EC, 0x1EE, 0x1EE, - 0x1F1, 0x1F1, + 0x1F1, 0x1F2, 0x1F4, 0x1F4, 0x1F6, 0x1F8, 0x1FA, 0x1FA, @@ -1910,11 +1910,14 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C 0x1F5D, 0x1F5D, 0x1F5F, 0x1F5F, 0x1F68, 0x1F6F, - 0x1FB8, 0x1FBB, - 0x1FC8, 0x1FCB, + 0x1F88, 0x1F8F, + 0x1F98, 0x1F9F, + 0x1FA8, 0x1FAF, + 0x1FB8, 0x1FBC, + 0x1FC8, 0x1FCC, 0x1FD8, 0x1FDB, 0x1FE8, 0x1FEC, - 0x1FF8, 0x1FFB, + 0x1FF8, 0x1FFC, 0x2102, 0x2102, 0x2107, 0x2107, 0x210B, 0x210D, @@ -2455,7 +2458,7 @@ pm_encoding_cesu_8_isupper_char(const uint8_t *b, ptrdiff_t n) { /** * Each element of the following table contains a bitfield that indicates a - * piece of information about the corresponding ASCII character. + * piece of information about the corresponding US-ASCII character. */ static const uint8_t pm_encoding_ascii_table[256] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F @@ -3624,7 +3627,7 @@ static const uint8_t pm_encoding_windows_1250_table[256] = { 0, 0, 0, 7, 0, 7, 0, 0, 0, 0, 7, 0, 0, 0, 0, 7, // Ax 0, 0, 0, 3, 0, 3, 0, 0, 0, 3, 3, 0, 7, 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 + 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, 0, 3, 3, 3, 3, 3, 3, 3, 0, // Fx }; @@ -3672,7 +3675,7 @@ static const uint8_t pm_encoding_windows_1252_table[256] = { 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 + 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, 0, 3, 3, 3, 3, 3, 3, 3, 3, // Fx }; @@ -4022,7 +4025,7 @@ pm_encoding_cp949_char_width(const uint8_t *b, ptrdiff_t n) { } // These are the double byte characters - if ((n > 1) && (b[0] >= 0x81 && b[0] <= 0xfe) && (b[1] >= 0x41 && b[1] <= 0xfe)) { + if ((n > 1) && (b[0] >= 0x81 && b[0] <= 0xFE) && ((b[1] >= 0x41 && b[1] <= 0x5A) || (b[1] >= 0x61 && b[1] <= 0x7A) || (b[1] >= 0x81 && b[1] <= 0xFE))) { return 2; } @@ -4096,6 +4099,27 @@ pm_encoding_euc_jp_char_width(const uint8_t *b, ptrdiff_t n) { return 0; } +/** + * Returns the size of the next character in the EUC-JP encoding if it is an + * uppercase character. + */ +static bool +pm_encoding_euc_jp_isupper_char(const uint8_t *b, ptrdiff_t n) { + size_t width = pm_encoding_euc_jp_char_width(b, n); + + if (width == 1) { + return pm_encoding_ascii_isupper_char(b, n); + } else if (width == 2) { + return ( + (b[0] == 0xA3 && b[1] >= 0xC1 && b[1] <= 0xDA) || + (b[0] == 0xA6 && b[1] >= 0xA1 && b[1] <= 0xB8) || + (b[0] == 0xA7 && b[1] >= 0xA1 && b[1] <= 0xC1) + ); + } else { + return false; + } +} + /** * Returns the size of the next character in the EUC-KR encoding, or 0 if a * character cannot be decoded from the given bytes. @@ -4201,18 +4225,59 @@ pm_encoding_gbk_char_width(const uint8_t *b, ptrdiff_t n) { static size_t pm_encoding_shift_jis_char_width(const uint8_t *b, ptrdiff_t n) { // These are the single byte characters. - if (*b < 0x80 || (*b >= 0xA1 && *b <= 0xDF)) { + if (b[0] < 0x80 || (b[0] >= 0xA1 && b[0] <= 0xDF)) { return 1; } // These are the double byte characters. - if ((n > 1) && ((b[0] >= 0x81 && b[0] <= 0x9F) || (b[0] >= 0xE0 && b[0] <= 0xFC)) && (b[1] >= 0x40 && b[1] <= 0xFC)) { + if ((n > 1) && ((b[0] >= 0x81 && b[0] <= 0x9F) || (b[0] >= 0xE0 && b[0] <= 0xFC)) && (b[1] >= 0x40 && b[1] <= 0xFC && b[1] != 0x7F)) { return 2; } return 0; } +/** + * Returns the size of the next character in the Shift_JIS encoding if it is an + * alphanumeric character. + */ +static size_t +pm_encoding_shift_jis_alnum_char(const uint8_t *b, ptrdiff_t n) { + size_t width = pm_encoding_shift_jis_char_width(b, n); + return width == 1 ? ((b[0] >= 0x80) || pm_encoding_ascii_alnum_char(b, n)) : width; +} + +/** + * Returns the size of the next character in the Shift_JIS encoding if it is an + * alphabetical character. + */ +static size_t +pm_encoding_shift_jis_alpha_char(const uint8_t *b, ptrdiff_t n) { + size_t width = pm_encoding_shift_jis_char_width(b, n); + return width == 1 ? ((b[0] >= 0x80) || pm_encoding_ascii_alpha_char(b, n)) : width; +} + +/** + * Returns the size of the next character in the Shift_JIS encoding if it is an + * uppercase character. + */ +static bool +pm_encoding_shift_jis_isupper_char(const uint8_t *b, ptrdiff_t n) { + size_t width = pm_encoding_shift_jis_char_width(b, n); + + if (width == 1) { + return pm_encoding_ascii_isupper_char(b, n); + } else if (width == 2) { + return ( + ((b[0] == 0x82) && (b[1] >= 0x60 && b[1] <= 0x79)) || + ((b[0] == 0x83) && (b[1] >= 0x9F && b[1] <= 0xB6)) || + ((b[0] == 0x84) && (b[1] >= 0x40 && b[1] <= 0x60)) + ); + } else { + return width; + } +} + /** * This is the table of all of the encodings that prism supports. */ @@ -4270,7 +4335,7 @@ const pm_encoding_t pm_encodings[] = { .char_width = pm_encoding_euc_jp_char_width, .alnum_char = pm_encoding_ascii_alnum_char_7bit, .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .isupper_char = pm_encoding_euc_jp_isupper_char, .multibyte = true }, [PM_ENCODING_CP850] = { @@ -4334,7 +4399,7 @@ const pm_encoding_t pm_encodings[] = { .char_width = pm_encoding_euc_jp_char_width, .alnum_char = pm_encoding_ascii_alnum_char_7bit, .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .isupper_char = pm_encoding_euc_jp_isupper_char, .multibyte = true }, [PM_ENCODING_EUC_JP_MS] = { @@ -4342,7 +4407,7 @@ const pm_encoding_t pm_encodings[] = { .char_width = pm_encoding_euc_jp_char_width, .alnum_char = pm_encoding_ascii_alnum_char_7bit, .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .isupper_char = pm_encoding_euc_jp_isupper_char, .multibyte = true }, [PM_ENCODING_EUC_JIS_2004] = { @@ -4350,7 +4415,7 @@ const pm_encoding_t pm_encodings[] = { .char_width = pm_encoding_euc_jp_char_width, .alnum_char = pm_encoding_ascii_alnum_char_7bit, .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .isupper_char = pm_encoding_euc_jp_isupper_char, .multibyte = true }, [PM_ENCODING_EUC_KR] = { @@ -4708,9 +4773,9 @@ const pm_encoding_t pm_encodings[] = { [PM_ENCODING_MAC_JAPANESE] = { .name = "MacJapanese", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_MAC_ROMAN] = { @@ -4756,33 +4821,33 @@ const pm_encoding_t pm_encodings[] = { [PM_ENCODING_SHIFT_JIS] = { .name = "Shift_JIS", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_SJIS_DOCOMO] = { .name = "SJIS-DoCoMo", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_SJIS_KDDI] = { .name = "SJIS-KDDI", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_SJIS_SOFTBANK] = { .name = "SJIS-SoftBank", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_STATELESS_ISO_2022_JP] = { @@ -4924,9 +4989,9 @@ const pm_encoding_t pm_encodings[] = { [PM_ENCODING_WINDOWS_31J] = { .name = "Windows-31J", .char_width = pm_encoding_shift_jis_char_width, - .alnum_char = pm_encoding_ascii_alnum_char_7bit, - .alpha_char = pm_encoding_ascii_alpha_char_7bit, - .isupper_char = pm_encoding_ascii_isupper_char_7bit, + .alnum_char = pm_encoding_shift_jis_alnum_char, + .alpha_char = pm_encoding_shift_jis_alpha_char, + .isupper_char = pm_encoding_shift_jis_isupper_char, .multibyte = true }, [PM_ENCODING_WINDOWS_874] = { From c9b6cd4223ec21e8eea65babd2543c6fbca57890 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:13:23 -0500 Subject: [PATCH 101/147] Remove unused rb_objspace_each_objects_without_setup --- gc.c | 6 ------ internal/gc.h | 4 ---- 2 files changed, 10 deletions(-) diff --git a/gc.c b/gc.c index a2b8589e4b686e..68df409602cc88 100644 --- a/gc.c +++ b/gc.c @@ -3738,12 +3738,6 @@ objspace_each_pages(rb_objspace_t *objspace, each_page_callback *callback, void objspace_each_exec(protected, &each_obj_data); } -void -rb_objspace_each_objects_without_setup(each_obj_callback *callback, void *data) -{ - objspace_each_objects(&rb_objspace, callback, data, FALSE); -} - struct os_each_struct { size_t num; VALUE of; diff --git a/internal/gc.h b/internal/gc.h index 89f566cf8dd46f..a74ad52782c16a 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -271,10 +271,6 @@ void rb_objspace_each_objects( int (*callback)(void *start, void *end, size_t stride, void *data), void *data); -void rb_objspace_each_objects_without_setup( - int (*callback)(void *, void *, size_t, void *), - void *data); - size_t rb_gc_obj_slot_size(VALUE obj); VALUE rb_gc_disable_no_rest(void); From b8572c3f16f1633b25d3a2e9bf98d3454f881a57 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Mon, 26 Feb 2024 12:09:34 -0800 Subject: [PATCH 102/147] BASERUBY is now >= 3.0 --- doc/contributing/building_ruby.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index aefad735306f12..18464458896b74 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -17,7 +17,7 @@ * autoconf - 2.67 or later * gperf - 3.1 or later * Usually unneeded; only if you edit some source files using gperf - * ruby - 2.7 or later + * ruby - 3.0 or later * We can upgrade this version to system ruby version of the latest Ubuntu LTS. 2. Install optional, recommended dependencies: From d2da774f870ecf51f465dd4081a7349812efaac4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 31 Jan 2024 13:49:31 +0900 Subject: [PATCH 103/147] [rubygems/rubygems] Rename wrapper files for vendored libraries with 'vendored_' prefix https://github.com/rubygems/rubygems/commit/cfc908c8c1 --- lib/rubygems/command.rb | 2 +- lib/rubygems/command_manager.rb | 2 +- lib/rubygems/dependency_list.rb | 2 +- lib/rubygems/gemcutter_utilities.rb | 2 +- lib/rubygems/net/http.rb | 3 --- lib/rubygems/remote_fetcher.rb | 2 +- lib/rubygems/request.rb | 2 +- lib/rubygems/request_set.rb | 2 +- lib/rubygems/s3_uri_signer.rb | 2 +- .../vendor/molinillo/lib/molinillo/dependency_graph.rb | 2 +- lib/rubygems/vendored_net_http.rb | 3 +++ lib/rubygems/{optparse.rb => vendored_optparse.rb} | 0 lib/rubygems/{timeout.rb => vendored_timeout.rb} | 0 lib/rubygems/{tsort.rb => vendored_tsort.rb} | 0 test/rubygems/test_bundled_ca.rb | 2 +- test/rubygems/test_gem_request_connection_pools.rb | 2 +- test/rubygems/test_gem_stream_ui.rb | 2 +- 17 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 lib/rubygems/net/http.rb create mode 100644 lib/rubygems/vendored_net_http.rb rename lib/rubygems/{optparse.rb => vendored_optparse.rb} (100%) rename lib/rubygems/{timeout.rb => vendored_timeout.rb} (100%) rename lib/rubygems/{tsort.rb => vendored_tsort.rb} (100%) diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index 06ec2a5bdda2ae..ec498a8b9409b8 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require_relative "optparse" +require_relative "vendored_optparse" require_relative "requirement" require_relative "user_interaction" diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index ee28dce62624aa..c2e4f4ce49ebc4 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -106,7 +106,7 @@ def self.reset # Register all the subcommands supported by the gem command. def initialize - require_relative "timeout" + require_relative "vendored_timeout" @commands = {} BUILTIN_COMMANDS.each do |name| diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb index 30098ff0b574c0..ad5e59e8c173f1 100644 --- a/lib/rubygems/dependency_list.rb +++ b/lib/rubygems/dependency_list.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require_relative "tsort" +require_relative "vendored_tsort" require_relative "deprecate" ## diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index ba356bc38c9ded..a8361b7ff1adbe 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -85,7 +85,7 @@ def host # If +allowed_push_host+ metadata is present, then it will only allow that host. def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scope: nil, credentials: {}, &block) - require_relative "net/http" + require_relative "vendored_net_http" self.host = host if host unless self.host diff --git a/lib/rubygems/net/http.rb b/lib/rubygems/net/http.rb deleted file mode 100644 index e2973ac24adb78..00000000000000 --- a/lib/rubygems/net/http.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require_relative "../vendor/net-http/lib/net/http" diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 3c8f79f9a7947b..c3a41592f670f5 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -74,7 +74,7 @@ def self.fetcher def initialize(proxy=nil, dns=nil, headers={}) require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled - require_relative "net/http" + require_relative "vendored_net_http" require "stringio" require_relative "vendor/uri/lib/uri" diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb index a8c1549e09a825..9116785231ea10 100644 --- a/lib/rubygems/request.rb +++ b/lib/rubygems/request.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "net/http" +require_relative "vendored_net_http" require_relative "user_interaction" class Gem::Request diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index 02b347766167e1..875df7e0198fe4 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "tsort" +require_relative "vendored_tsort" ## # A RequestSet groups a request to activate a set of dependencies. diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb index 06dee3afe0fdf4..7c95a9d4f5848a 100644 --- a/lib/rubygems/s3_uri_signer.rb +++ b/lib/rubygems/s3_uri_signer.rb @@ -140,7 +140,7 @@ def base64_uri_escape(str) end def ec2_metadata_credentials_json - require_relative "net/http" + require_relative "vendored_net_http" require_relative "request" require_relative "request/connection_pools" require "json" diff --git a/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb index b9ebe2951c4e75..3a675af56498e7 100644 --- a/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../../../../tsort' +require_relative '../../../tsort/lib/tsort' require_relative 'dependency_graph/log' require_relative 'dependency_graph/vertex' diff --git a/lib/rubygems/vendored_net_http.rb b/lib/rubygems/vendored_net_http.rb new file mode 100644 index 00000000000000..0c0f8d446d6394 --- /dev/null +++ b/lib/rubygems/vendored_net_http.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "vendor/net-http/lib/net/http" diff --git a/lib/rubygems/optparse.rb b/lib/rubygems/vendored_optparse.rb similarity index 100% rename from lib/rubygems/optparse.rb rename to lib/rubygems/vendored_optparse.rb diff --git a/lib/rubygems/timeout.rb b/lib/rubygems/vendored_timeout.rb similarity index 100% rename from lib/rubygems/timeout.rb rename to lib/rubygems/vendored_timeout.rb diff --git a/lib/rubygems/tsort.rb b/lib/rubygems/vendored_tsort.rb similarity index 100% rename from lib/rubygems/tsort.rb rename to lib/rubygems/vendored_tsort.rb diff --git a/test/rubygems/test_bundled_ca.rb b/test/rubygems/test_bundled_ca.rb index 616b18ee83a00f..50e621f22b490b 100644 --- a/test/rubygems/test_bundled_ca.rb +++ b/test/rubygems/test_bundled_ca.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative "helper" -require "rubygems/net/http" +require "rubygems/vendored_net_http" require "rubygems/openssl" unless Gem::HAVE_OPENSSL diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb index 7a814d3acb4ef2..966447bff64192 100644 --- a/test/rubygems/test_gem_request_connection_pools.rb +++ b/test/rubygems/test_gem_request_connection_pools.rb @@ -2,7 +2,7 @@ require_relative "helper" require "rubygems/request" -require "rubygems/timeout" +require "rubygems/vendored_timeout" class TestGemRequestConnectionPool < Gem::TestCase class FakeHttp diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb index 92b3153ba05eac..b1fcb3bc26d710 100644 --- a/test/rubygems/test_gem_stream_ui.rb +++ b/test/rubygems/test_gem_stream_ui.rb @@ -2,7 +2,7 @@ require_relative "helper" require "rubygems/user_interaction" -require "rubygems/timeout" +require "rubygems/vendored_timeout" class TestGemStreamUI < Gem::TestCase # increase timeout with RJIT for --jit-wait testing From d220d273aa31672d46ebcc29df17260fb7c7f91b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 31 Jan 2024 14:08:33 +0900 Subject: [PATCH 104/147] [rubygems/rubygems] Use renamed file on bundler https://github.com/rubygems/rubygems/commit/d198ec36f2 --- lib/bundler/vendored_net_http.rb | 2 +- lib/bundler/vendored_timeout.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bundler/vendored_net_http.rb b/lib/bundler/vendored_net_http.rb index 908ec4bcafe306..59f234a758d5a4 100644 --- a/lib/bundler/vendored_net_http.rb +++ b/lib/bundler/vendored_net_http.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true begin - require "rubygems/net/http" + require "rubygems/vendored_net_http" rescue LoadError require "net/http" Gem::Net = Net diff --git a/lib/bundler/vendored_timeout.rb b/lib/bundler/vendored_timeout.rb index 34770f21167432..0be3d802fdf252 100644 --- a/lib/bundler/vendored_timeout.rb +++ b/lib/bundler/vendored_timeout.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true begin - require "rubygems/timeout" + require "rubygems/vendored_timeout" rescue LoadError require "timeout" Gem::Timeout = Timeout From 8b22198ee9baed58c4c7b578fb4cf133a8235ab8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 7 Feb 2024 17:56:37 +0900 Subject: [PATCH 105/147] [rubygems/rubygems] Use wrapper file for vendored tsort https://github.com/rubygems/rubygems/commit/93514afa28 --- lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb index 3a675af56498e7..2dbbc589dc7d5e 100644 --- a/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb +++ b/lib/rubygems/vendor/molinillo/lib/molinillo/dependency_graph.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../../../tsort/lib/tsort' +require_relative '../../../../vendored_tsort' require_relative 'dependency_graph/log' require_relative 'dependency_graph/vertex' From c3427265687d008612179410009868b5ec10b116 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 7 Feb 2024 18:46:17 +0900 Subject: [PATCH 106/147] [rubygems/rubygems] Keep compatiblity for RG 3.5 https://github.com/rubygems/rubygems/commit/d004e36c44 --- lib/bundler/vendored_net_http.rb | 8 ++++++-- lib/bundler/vendored_timeout.rb | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/bundler/vendored_net_http.rb b/lib/bundler/vendored_net_http.rb index 59f234a758d5a4..0dcabaa7d71987 100644 --- a/lib/bundler/vendored_net_http.rb +++ b/lib/bundler/vendored_net_http.rb @@ -3,6 +3,10 @@ begin require "rubygems/vendored_net_http" rescue LoadError - require "net/http" - Gem::Net = Net + begin + require "rubygems/net/http" + rescue LoadError + require "net/http" + Gem::Net = Net + end end diff --git a/lib/bundler/vendored_timeout.rb b/lib/bundler/vendored_timeout.rb index 0be3d802fdf252..9b2507c0cc8a13 100644 --- a/lib/bundler/vendored_timeout.rb +++ b/lib/bundler/vendored_timeout.rb @@ -3,6 +3,10 @@ begin require "rubygems/vendored_timeout" rescue LoadError - require "timeout" - Gem::Timeout = Timeout + begin + require "rubygems/timeout" + rescue LoadError + require "timeout" + Gem::Timeout = Timeout + end end From 81dded1044d0d045af10c916eaed9429a8509ae3 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 26 Feb 2024 19:43:50 +0900 Subject: [PATCH 107/147] [rubygems/rubygems] Skip to load vendored libraries if it's already loaded https://github.com/rubygems/rubygems/commit/3f5093fac9 --- lib/rubygems/vendored_net_http.rb | 4 +++- lib/rubygems/vendored_timeout.rb | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/vendored_net_http.rb b/lib/rubygems/vendored_net_http.rb index 0c0f8d446d6394..a84c52a9470675 100644 --- a/lib/rubygems/vendored_net_http.rb +++ b/lib/rubygems/vendored_net_http.rb @@ -1,3 +1,5 @@ # frozen_string_literal: true -require_relative "vendor/net-http/lib/net/http" +# Ruby 3.3 and RubyGems 3.5 is already load Gem::Timeout from lib/rubygems/net/http.rb +# We should avoid to load it again +require_relative "vendor/net-http/lib/net/http" unless defined?(Gem::Net::HTTP) diff --git a/lib/rubygems/vendored_timeout.rb b/lib/rubygems/vendored_timeout.rb index 6b8e1c7aa86eac..45541928e672d4 100644 --- a/lib/rubygems/vendored_timeout.rb +++ b/lib/rubygems/vendored_timeout.rb @@ -1,3 +1,5 @@ # frozen_string_literal: true -require_relative "vendor/timeout/lib/timeout" +# Ruby 3.3 and RubyGems 3.5 is already load Gem::Timeout from lib/rubygems/timeout.rb +# We should avoid to load it again +require_relative "vendor/timeout/lib/timeout" unless defined?(Gem::Timeout) From 7538703d1b69e5f3be04240f387dfbcb1f4e2d91 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:20:59 -0500 Subject: [PATCH 108/147] Make rb_objspace_data_type_memsize private rb_objspace_data_type_memsize is not used in the objspace module, so we can make it private. --- gc.c | 2 +- internal/gc.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gc.c b/gc.c index 68df409602cc88..a54cf52c17da50 100644 --- a/gc.c +++ b/gc.c @@ -3030,7 +3030,7 @@ rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type return obj; } -size_t +static size_t rb_objspace_data_type_memsize(VALUE obj) { size_t size = 0; diff --git a/internal/gc.h b/internal/gc.h index a74ad52782c16a..df5e4d8a3bcc7e 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -260,7 +260,6 @@ void rb_gc_ref_update_table_values_only(st_table *tbl); RUBY_SYMBOL_EXPORT_BEGIN /* exports for objspace module */ -size_t rb_objspace_data_type_memsize(VALUE obj); void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data); void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data); int rb_objspace_markable_object_p(VALUE obj); From 78ae6dbb11c1c6881ac599c3b91edaf0df4d7938 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:21:09 -0500 Subject: [PATCH 109/147] Remove rb_objspace_marked_object_p rb_objspace_marked_object_p is no longer used in the objspace module, so we can remove it. --- gc.c | 12 +----------- internal/gc.h | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/gc.c b/gc.c index a54cf52c17da50..c65ef5cb9615d1 100644 --- a/gc.c +++ b/gc.c @@ -6826,16 +6826,6 @@ rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr) } } -/* CAUTION: THIS FUNCTION ENABLE *ONLY BEFORE* SWEEPING. - * This function is only for GC_END_MARK timing. - */ - -int -rb_objspace_marked_object_p(VALUE obj) -{ - return RVALUE_MARKED(obj) ? TRUE : FALSE; -} - static inline void gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj) { @@ -9606,7 +9596,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, s GC_ASSERT(!RVALUE_MARKING((VALUE)src)); /* Save off bits for current object. */ - marked = rb_objspace_marked_object_p((VALUE)src); + marked = RVALUE_MARKED((VALUE)src); wb_unprotected = RVALUE_WB_UNPROTECTED((VALUE)src); uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src); bool remembered = RVALUE_REMEMBERED((VALUE)src); diff --git a/internal/gc.h b/internal/gc.h index df5e4d8a3bcc7e..325a95f4b4d780 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -264,7 +264,6 @@ void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), v void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data); int rb_objspace_markable_object_p(VALUE obj); int rb_objspace_internal_object_p(VALUE obj); -int rb_objspace_marked_object_p(VALUE obj); void rb_objspace_each_objects( int (*callback)(void *start, void *end, size_t stride, void *data), From 89f0c0ceb5e5e20c56e63498521966c499b361a5 Mon Sep 17 00:00:00 2001 From: ydah Date: Thu, 22 Feb 2024 19:48:41 +0900 Subject: [PATCH 110/147] Use `'\n'?` instead of `opt_nl` --- parse.y | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/parse.y b/parse.y index bee79c9f6c51bf..0d993add2cb8e2 100644 --- a/parse.y +++ b/parse.y @@ -3234,7 +3234,7 @@ endless_command : command $$ = rescued_expr(p, $1, $4, &@1, &@2, &@4); /*% ripper: rescue_mod!($:1, $:4) %*/ } - | keyword_not opt_nl endless_command + | keyword_not '\n'? endless_command { $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$); /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/ @@ -3268,7 +3268,7 @@ expr : command_call $$ = logop(p, idOR, $1, $3, &@2, &@$); /*% ripper: binary!($:1, ID2VAL(idOR), $:3) %*/ } - | keyword_not opt_nl expr + | keyword_not '\n'? expr { $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$); /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/ @@ -3988,13 +3988,13 @@ arg : lhs '=' lex_ctxt arg_rhs $$ = logop(p, idOROP, $1, $3, &@2, &@$); /*% ripper: binary!($:1, ID2VAL(idOROP), $:3) %*/ } - | keyword_defined opt_nl begin_defined arg + | keyword_defined '\n'? begin_defined arg { p->ctxt.in_defined = $3.in_defined; $$ = new_defined(p, $4, &@$); /*% ripper: defined!($:4) %*/ } - | arg '?' arg opt_nl ':' arg + | arg '?' arg '\n'? ':' arg { value_expr($1); $$ = new_if(p, $1, $3, $6, &@$); @@ -4044,7 +4044,7 @@ endless_arg : arg %prec modifier_rescue $$ = rescued_expr(p, $1, $4, &@1, &@2, &@4); /*% ripper: rescue_mod!($:1, $:4) %*/ } - | keyword_not opt_nl endless_arg + | keyword_not '\n'? endless_arg { $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$); /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/ @@ -4408,7 +4408,7 @@ primary : literal $$ = NEW_YIELD(0, &@$); /*% ripper: yield0! %*/ } - | keyword_defined opt_nl '(' begin_defined expr rparen + | keyword_defined '\n'? '(' begin_defined expr rparen { p->ctxt.in_defined = $4.in_defined; $$ = new_defined(p, $5, &@$); @@ -5095,12 +5095,12 @@ block_param_def : '|' opt_bv_decl '|' ; -opt_bv_decl : opt_nl +opt_bv_decl : '\n'? { $$ = 0; /*% ripper: Qfalse %*/ } - | opt_nl ';' bv_decls opt_nl + | '\n'? ';' bv_decls '\n'? { $$ = 0; /*% ripper: get_value($:3) %*/ @@ -6942,20 +6942,16 @@ call_op2 : call_op | tCOLON2 ; -opt_nl : /* none */ - | '\n' - ; - -rparen : opt_nl ')' +rparen : '\n'? ')' ; -rbracket : opt_nl ']' +rbracket : '\n'? ']' ; -rbrace : opt_nl '}' +rbrace : '\n'? '}' ; -trailer : opt_nl +trailer : '\n'? | ',' ; From 54a5b829442eb7ed1f4a2794ebb26696cf784e64 Mon Sep 17 00:00:00 2001 From: Kenta Murata <3959+mrkn@users.noreply.github.com> Date: Tue, 27 Feb 2024 09:37:03 +0900 Subject: [PATCH 111/147] Handle zero-like imaginary part as zero in to_r (#9581) Fixes [Bug #5179] --- complex.c | 16 ++++++++++++---- spec/ruby/core/complex/to_r_spec.rb | 12 ++++++++++-- test/ruby/test_complex.rb | 23 +++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/complex.c b/complex.c index 8c32c605235257..92245bc9e83bdf 100644 --- a/complex.c +++ b/complex.c @@ -1841,9 +1841,11 @@ nucomp_to_f(VALUE self) * * Complex.rect(1, 0).to_r # => (1/1) * Complex.rect(1, Rational(0, 1)).to_r # => (1/1) + * Complex.rect(1, 0.0).to_r # => (1/1) * * Raises RangeError if self.imag is not exactly zero - * (either Integer(0) or Rational(0, _n_)). + * (either Integer(0) or Rational(0, _n_)) + * and self.imag.to_r is not exactly zero. * * Related: Complex#rationalize. */ @@ -1852,9 +1854,15 @@ nucomp_to_r(VALUE self) { get_dat1(self); - if (!k_exact_zero_p(dat->imag)) { - rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", - self); + if (RB_FLOAT_TYPE_P(dat->imag) && FLOAT_ZERO_P(dat->imag)) { + /* Do nothing here */ + } + else if (!k_exact_zero_p(dat->imag)) { + VALUE imag = rb_check_convert_type_with_id(dat->imag, T_RATIONAL, "Rational", idTo_r); + if (NIL_P(imag) || !k_exact_zero_p(imag)) { + rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", + self); + } } return f_to_r(dat->real); } diff --git a/spec/ruby/core/complex/to_r_spec.rb b/spec/ruby/core/complex/to_r_spec.rb index 45599214925a6e..788027a50039c5 100644 --- a/spec/ruby/core/complex/to_r_spec.rb +++ b/spec/ruby/core/complex/to_r_spec.rb @@ -34,8 +34,16 @@ end describe "when the imaginary part is Float 0.0" do - it "raises RangeError" do - -> { Complex(0, 0.0).to_r }.should raise_error(RangeError) + ruby_version_is ''...'3.4' do + it "raises RangeError" do + -> { Complex(0, 0.0).to_r }.should raise_error(RangeError) + end + end + + ruby_version_is '3.4' do + it "returns a Rational" do + Complex(0, 0.0).to_r.should == 0r + end end end end diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index 8817a6287342b8..c0cfb732357e4d 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -1054,6 +1054,29 @@ def test_to_r assert_raise(RangeError){Rational(Complex(3,2))} end + def test_to_r_with_float + assert_equal(Rational(3), Complex(3, 0.0).to_r) + assert_raise(RangeError){Complex(3, 1.0).to_r} + end + + def test_to_r_with_numeric_obj + c = Class.new(Numeric) + + num = 0 + c.define_method(:to_s) { num.to_s } + c.define_method(:==) { num == it } + c.define_method(:<) { num < it } + + o = c.new + assert_equal(Rational(3), Complex(3, o).to_r) + + num = 1 + assert_raise(RangeError){Complex(3, o).to_r} + + c.define_method(:to_r) { 0r } + assert_equal(Rational(3), Complex(3, o).to_r) + end + def test_to_c c = nil.to_c assert_equal([0,0], [c.real, c.imag]) From cbbb98ba5e856c4413dcb27460b32be8865683ab Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 Feb 2024 10:18:06 +0900 Subject: [PATCH 112/147] [ruby/tempfile] Fix for environment without git https://github.com/ruby/tempfile/commit/f224164979 --- lib/tempfile.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec index 0b4c6cc8867b8c..0b362b0a86763d 100644 --- a/lib/tempfile.gemspec +++ b/lib/tempfile.gemspec @@ -23,7 +23,7 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. gemspec = File.basename(__FILE__) - spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL, exception: false) do |ls| ls.readlines("\x0", chomp: true).reject do |f| (f == gemspec) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) From 316d1e1014e99b750d6ac5d5245b1e0fee3662c3 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 Feb 2024 10:17:25 +0900 Subject: [PATCH 113/147] [ruby/tmpdir] Fix for environment without git https://github.com/ruby/tmpdir/commit/3f1f2260eb --- lib/tmpdir.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec index d4bb892cc6a5fd..4c96e5984bf818 100644 --- a/lib/tmpdir.gemspec +++ b/lib/tmpdir.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |spec| # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. gemspec = File.basename(__FILE__) - spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls| + spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL, exception: false) do |ls| ls.readlines("\x0", chomp: true).reject do |f| (f == gemspec) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) From 1745dd2691556a8c13e93f22001ae79b0b5046c5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 Feb 2024 11:47:50 +0900 Subject: [PATCH 114/147] Ignore miss-and-revised commits [ci skip] --- .git-blame-ignore-revs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 1bf7db40ade99d..1cafd3df75d73e 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -26,3 +26,7 @@ fc4acf8cae82e5196186d3278d831f2438479d91 # Make prism_compile.c indentation consistent 40b2c8e5e7e6e5f83cee9276dc9c1922a69292d6 d2c5867357ed88eccc28c2b3bd4a46e206e7ff85 + +# Miss-and-revived commits +a0f7de814ae5c299d6ce99bed5fb308a05d50ba0 +d4e24021d39e1f80f0055b55d91f8d5f22e15084 From bfb2dc8acfd7d7c825b7ba0f1eb50ec92631362c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20=C5=A0im=C3=A1nek?= Date: Mon, 25 Oct 2021 02:47:04 +0200 Subject: [PATCH 115/147] [rubygems/rubygems] Warn on empty or open required_ruby_version specification attribute. https://github.com/rubygems/rubygems/commit/e4bb33747a --- lib/rubygems/specification_policy.rb | 8 +++ .../specifications/rubyforge-0.0.1.gemspec | 21 ++++---- .../test_gem_commands_build_command.rb | 2 + test/rubygems/test_gem_specification.rb | 49 +++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index 27c2681533f491..516c26f53c8aa5 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -103,6 +103,8 @@ def validate_optional(strict) validate_dependencies + validate_required_ruby_version + validate_extensions validate_removed_attributes @@ -227,6 +229,12 @@ def validate_dependencies # :nodoc: end end + def validate_required_ruby_version + if @specification.required_ruby_version.requirements == [Gem::Requirement::DefaultRequirement] + warning "make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute" + end + end + ## # Issues a warning for each file to be packaged which is world-readable. # diff --git a/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/test/rubygems/specifications/rubyforge-0.0.1.gemspec index 49619bf5691632..0421b675a0f974 100644 --- a/test/rubygems/specifications/rubyforge-0.0.1.gemspec +++ b/test/rubygems/specifications/rubyforge-0.0.1.gemspec @@ -1,14 +1,15 @@ # frozen_string_literal: true Gem::Specification.new do |s| - s.name = "rubyforge" - s.version = "0.0.1" - s.platform = "ruby" - s.require_paths = ["lib"] - s.summary = "A very bar gem" - s.authors = ["unknown"] - s.license = "MIT" - s.homepage = "http://example.com" - s.files = ["README.md"] - s.rubyforge_project = "abc" + s.name = "rubyforge" + s.version = "0.0.1" + s.platform = "ruby" + s.require_paths = ["lib"] + s.summary = "A very bar gem" + s.authors = ["unknown"] + s.license = "MIT" + s.homepage = "http://example.com" + s.files = ["README.md"] + s.rubyforge_project = "abc" + s.required_ruby_version = ">= 1.9.3" end diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 983cf7b472282f..d44126d2046a94 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -28,6 +28,7 @@ def setup @gem = util_spec "some_gem" do |s| s.license = "AGPL-3.0-only" s.files = ["README.md"] + s.required_ruby_version = "2.3.0" end @cmd = Gem::Commands::BuildCommand.new @@ -178,6 +179,7 @@ def test_execute_rubyforge_project_warning def test_execute_strict_with_warnings bad_gem = util_spec "some_bad_gem" do |s| s.files = ["README.md"] + s.required_ruby_version = ">= 1.9.3" end gemspec_file = File.join(@tempdir, bad_gem.spec_name) diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 9aa88fd5a3aa8e..9e05649f7cfd03 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -90,6 +90,7 @@ def setup Gem.instance_variable_set(:'@default_source_date_epoch', nil) @a1 = util_spec "a", "1" do |s| + s.required_ruby_version = ">= 2.3.0" s.executable = "exec" s.test_file = "test/suite.rb" s.requirements << "A working computer" @@ -2707,6 +2708,53 @@ def test_validate_dependencies_allowed_duplicates end end + def test_validate_no_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + use_ui @ui do + @a1.required_ruby_version = nil # reset + @a1.validate + end + + assert_equal <<-EXPECTED, @ui.error +#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute +#{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + end + end + + def test_validate_open_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + @a1.required_ruby_version = ">= 0" + + use_ui @ui do + @a1.validate + end + + assert_equal <<-EXPECTED, @ui.error +#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute +#{w}: See https://guides.rubygems.org/specification-reference/ for help + EXPECTED + end + end + + def test_validate_valid_required_ruby_versions + util_setup_validate + + Dir.chdir @tempdir do + @a1.required_ruby_version = ">= 2.3.0" + + use_ui @ui do + @a1.validate + end + + assert_equal "", @ui.error, "warning" + end + end + def test_validate_prerelease_dependencies_with_prerelease_version util_setup_validate @@ -3683,6 +3731,7 @@ def test_metadata_link_validation_warns_for_duplicates Dir.chdir @tempdir do @m2 = quick_gem "m", "2" do |s| + s.required_ruby_version = ">= 2.3.0" s.files = %w[lib/code.rb] s.licenses = "BSD-2-Clause" s.metadata = { From 3ca8b4aee0bf99b34c392b4b449541db82781284 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 26 Feb 2024 22:11:33 -0500 Subject: [PATCH 116/147] [ruby/prism] Support -p, -n, -a, and -l command line options https://github.com/ruby/prism/commit/959eb506ca --- lib/prism/ffi.rb | 12 ++ prism/extension.c | 16 +++ prism/node.h | 9 ++ prism/options.c | 38 ++++- prism/options.h | 49 ++++++- prism/parser.h | 24 ++++ prism/prism.c | 244 +++++++++++++++++++++++++++++++- prism/templates/src/node.c.erb | 12 ++ test/prism/command_line_test.rb | 61 ++++++++ 9 files changed, 457 insertions(+), 8 deletions(-) create mode 100644 test/prism/command_line_test.rb diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index d09198a25d6b4f..0f262573de7247 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -342,6 +342,18 @@ def dump_options(options) template << "C" values << (options.fetch(:frozen_string_literal, false) ? 1 : 0) + template << "C" + values << (options.fetch(:command_line_p, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:command_line_n, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:command_line_l, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:command_line_a, false) ? 1 : 0) + template << "C" values << { nil => 0, "3.3.0" => 1, "3.4.0" => 0, "latest" => 0 }.fetch(options[:version]) diff --git a/prism/extension.c b/prism/extension.c index d0ffa2f9361a0a..7bcb5f65c181e2 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -29,6 +29,10 @@ ID rb_option_id_line; ID rb_option_id_frozen_string_literal; ID rb_option_id_version; ID rb_option_id_scopes; +ID rb_option_id_command_line_p; +ID rb_option_id_command_line_n; +ID rb_option_id_command_line_l; +ID rb_option_id_command_line_a; /******************************************************************************/ /* IO of Ruby code */ @@ -149,6 +153,14 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { } } else if (key_id == rb_option_id_scopes) { if (!NIL_P(value)) build_options_scopes(options, value); + } else if (key_id == rb_option_id_command_line_p) { + if (!NIL_P(value)) pm_options_command_line_p_set(options, value == Qtrue); + } else if (key_id == rb_option_id_command_line_n) { + if (!NIL_P(value)) pm_options_command_line_n_set(options, value == Qtrue); + } else if (key_id == rb_option_id_command_line_l) { + if (!NIL_P(value)) pm_options_command_line_l_set(options, value == Qtrue); + } else if (key_id == rb_option_id_command_line_a) { + if (!NIL_P(value)) pm_options_command_line_a_set(options, value == Qtrue); } else { rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key); } @@ -1232,6 +1244,10 @@ Init_prism(void) { rb_option_id_frozen_string_literal = rb_intern_const("frozen_string_literal"); rb_option_id_version = rb_intern_const("version"); rb_option_id_scopes = rb_intern_const("scopes"); + rb_option_id_command_line_p = rb_intern_const("command_line_p"); + rb_option_id_command_line_n = rb_intern_const("command_line_n"); + rb_option_id_command_line_l = rb_intern_const("command_line_l"); + rb_option_id_command_line_a = rb_intern_const("command_line_a"); /** * The version of the prism library. diff --git a/prism/node.h b/prism/node.h index 9c37c9decce569..76eb720978145d 100644 --- a/prism/node.h +++ b/prism/node.h @@ -29,6 +29,15 @@ bool pm_node_list_grow(pm_node_list_t *list); */ void pm_node_list_append(pm_node_list_t *list, pm_node_t *node); +/** + * Prepend a new node onto the beginning of the node list. + * + * @param list The list to prepend to. + * @param node The node to prepend. + */ +void +pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node); + /** * Free the internal memory associated with the given node list. * diff --git a/prism/options.c b/prism/options.c index a7f2dfdc760d23..54fd1bc01436b9 100644 --- a/prism/options.c +++ b/prism/options.c @@ -32,6 +32,38 @@ pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_l options->frozen_string_literal = frozen_string_literal; } +/** + * Sets the -p command line option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_command_line_p_set(pm_options_t *options, bool command_line_p) { + options->command_line_p = command_line_p; +} + +/** + * Sets the -n command line option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_command_line_n_set(pm_options_t *options, bool command_line_n) { + options->command_line_n = command_line_n; +} + +/** + * Sets the -l command line option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_command_line_l_set(pm_options_t *options, bool command_line_l) { + options->command_line_l = command_line_l; +} + +/** + * Sets the -a command line option on the given options struct. + */ +PRISM_EXPORTED_FUNCTION void +pm_options_command_line_a_set(pm_options_t *options, bool command_line_a) { + options->command_line_a = command_line_a; +} + /** * Set the version option on the given options struct by parsing the given * string. If the string contains an invalid option, this returns false. @@ -193,7 +225,11 @@ pm_options_read(pm_options_t *options, const char *data) { data += encoding_length; } - options->frozen_string_literal = *data++; + options->frozen_string_literal = (*data++) ? true : false; + options->command_line_p = (*data++) ? true : false; + options->command_line_n = (*data++) ? true : false; + options->command_line_l = (*data++) ? true : false; + options->command_line_a = (*data++) ? true : false; options->version = (pm_options_version_t) *data++; uint32_t scopes_count = pm_options_read_u32(data); diff --git a/prism/options.h b/prism/options.h index bc5fa2677aa1bb..4a60fc266ae940 100644 --- a/prism/options.h +++ b/prism/options.h @@ -78,6 +78,18 @@ typedef struct { /** Whether or not the frozen string literal option has been set. */ bool frozen_string_literal; + + /** Whether or not the -p command line option has been set. */ + bool command_line_p; + + /** Whether or not the -n command line option has been set. */ + bool command_line_n; + + /** Whether or not the -l command line option has been set. */ + bool command_line_l; + + /** Whether or not the -a command line option has been set. */ + bool command_line_a; } pm_options_t; /** @@ -112,6 +124,38 @@ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, cons */ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal); +/** + * Sets the -p command line option on the given options struct. + * + * @param options The options struct to set the -p command line option on. + * @param command_line_p The -p command line option to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_command_line_p_set(pm_options_t *options, bool command_line_p); + +/** + * Sets the -n command line option on the given options struct. + * + * @param options The options struct to set the -n command line option on. + * @param command_line_n The -n command line option to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_command_line_n_set(pm_options_t *options, bool command_line_n); + +/** + * Sets the -l command line option on the given options struct. + * + * @param options The options struct to set the -l command line option on. + * @param command_line_l The -l command line option to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_command_line_l_set(pm_options_t *options, bool command_line_l); + +/** + * Sets the -a command line option on the given options struct. + * + * @param options The options struct to set the -a command line option on. + * @param command_line_a The -a command line option to set. + */ +PRISM_EXPORTED_FUNCTION void pm_options_command_line_a_set(pm_options_t *options, bool command_line_a); + /** * Set the version option on the given options struct by parsing the given * string. If the string contains an invalid option, this returns false. @@ -186,7 +230,10 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options); * | `4` | the length the encoding | * | ... | the encoding bytes | * | `1` | frozen string literal | - * | `1` | suppress warnings | + * | `1` | -p command line option | + * | `1` | -n command line option | + * | `1` | -l command line option | + * | `1` | -a command line option | * | `1` | the version | * | `4` | the number of scopes | * | ... | the scopes | diff --git a/prism/parser.h b/prism/parser.h index 86976fc5d2d321..b790489d7d5f66 100644 --- a/prism/parser.h +++ b/prism/parser.h @@ -736,6 +736,30 @@ struct pm_parser { * a true value. */ bool frozen_string_literal; + + /** + * Whether or not -p was present on the command line that invoked the + * parser. -p prints the value of $_ at the end of each loop. + */ + bool command_line_p; + + /** + * Whether or not -n was present on the command line that invoked the + * parser. -n wraps the script in a while gets loop. + */ + bool command_line_n; + + /** + * Whether or not -l was present on the command line that invoked the + * parser. -l chomps the input line by default. + */ + bool command_line_l; + + /** + * Whether or not -a was present on the command line that invoked the + * parser. -a splits the input line $_ into $F. + */ + bool command_line_a; }; #endif diff --git a/prism/prism.c b/prism/prism.c index fecc25336dba9f..0cedf924e439d2 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -1904,6 +1904,24 @@ pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *o return node; } +/** + * Allocate and initialize a new synthesized CallNode node from a call expression. + */ +static pm_call_node_t * +pm_call_node_call_synthesized_create(pm_parser_t *parser, pm_node_t *receiver, const char *message, pm_arguments_node_t *arguments) { + pm_call_node_t *node = pm_call_node_create(parser, 0); + node->base.location.start = parser->start; + node->base.location.end = parser->end; + + node->receiver = receiver; + node->call_operator_loc = (pm_location_t) { .start = NULL, .end = NULL }; + node->message_loc = (pm_location_t) { .start = NULL, .end = NULL }; + node->arguments = arguments; + + node->name = pm_parser_constant_id_constant(parser, message, strlen(message)); + return node; +} + /** * Allocate and initialize a new CallNode node from a call to a method name * without a receiver that could not have been a local variable read. @@ -1925,6 +1943,22 @@ pm_call_node_fcall_create(pm_parser_t *parser, pm_token_t *message, pm_arguments return node; } +/** + * Allocate and initialize a new CallNode node from a synthesized call to a + * method name with the given arguments. + */ +static pm_call_node_t * +pm_call_node_fcall_synthesized_create(pm_parser_t *parser, pm_arguments_node_t *arguments, pm_constant_id_t name) { + pm_call_node_t *node = pm_call_node_create(parser, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY); + + node->base.location.start = parser->start; + node->base.location.end = parser->start; + node->arguments = arguments; + + node->name = name; + return node; +} + /** * Allocate and initialize a new CallNode node from a not expression. */ @@ -3568,7 +3602,25 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) } /** - * Allocate a new GlobalVariableWriteNode node. + * Allocate and initialize a new synthesized GlobalVariableReadNode node. + */ +static pm_global_variable_read_node_t * +pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name) { + pm_global_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_read_node_t); + + *node = (pm_global_variable_read_node_t) { + { + .type = PM_GLOBAL_VARIABLE_READ_NODE, + .location = { .start = parser->start, .end = parser->start } + }, + .name = name + }; + + return node; +} + +/** + * Allocate and initialize a new GlobalVariableWriteNode node. */ static pm_global_variable_write_node_t * pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) { @@ -3591,6 +3643,27 @@ pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, con return node; } +/** + * Allocate and initialize a new synthesized GlobalVariableWriteNode node. + */ +static pm_global_variable_write_node_t * +pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name, pm_node_t *value) { + pm_global_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_write_node_t); + + *node = (pm_global_variable_write_node_t) { + { + .type = PM_GLOBAL_VARIABLE_WRITE_NODE, + .location = { .start = parser->start, .end = parser->start } + }, + .name = name, + .name_loc = { .start = parser->start, .end = parser->start }, + .operator_loc = { .start = parser->start, .end = parser->start }, + .value = value + }; + + return node; +} + /** * Allocate a new HashNode node. */ @@ -5678,20 +5751,37 @@ pm_statements_node_location_set(pm_statements_node_t *node, const uint8_t *start } /** - * Append a new node to the given StatementsNode node's body. + * Update the location of the statements node based on the statement that is + * being added to the list. */ -static void -pm_statements_node_body_append(pm_statements_node_t *node, pm_node_t *statement) { +static inline void +pm_statements_node_body_update(pm_statements_node_t *node, pm_node_t *statement) { if (pm_statements_node_body_length(node) == 0 || statement->location.start < node->base.location.start) { node->base.location.start = statement->location.start; } + if (statement->location.end > node->base.location.end) { node->base.location.end = statement->location.end; } +} +/** + * Append a new node to the given StatementsNode node's body. + */ +static void +pm_statements_node_body_append(pm_statements_node_t *node, pm_node_t *statement) { + pm_statements_node_body_update(node, statement); pm_node_list_append(&node->body, statement); + pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); +} - // Every statement gets marked as a place where a newline can occur. +/** + * Prepend a new node to the given StatementsNode node's body. + */ +static void +pm_statements_node_body_prepend(pm_statements_node_t *node, pm_node_t *statement) { + pm_statements_node_body_update(node, statement); + pm_node_list_prepend(&node->body, statement); pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE); } @@ -5898,6 +5988,27 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { return node; } +/** + * Allocate and initialize a new synthesized SymbolNode node. + */ +static pm_symbol_node_t * +pm_symbol_node_synthesized_create(pm_parser_t *parser, const char *content) { + pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t); + + *node = (pm_symbol_node_t) { + { + .type = PM_SYMBOL_NODE, + .flags = PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING, + .location = { .start = parser->start, .end = parser->start } + }, + .value_loc = { .start = parser->start, .end = parser->start }, + .unescaped = { 0 } + }; + + pm_string_constant_init(&node->unescaped, content, strlen(content)); + return node; +} + /** * Check if the given node is a label in a hash. */ @@ -6000,6 +6111,22 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) { return node; } +/** + * Allocate and initialize a new synthesized TrueNode node. + */ +static pm_true_node_t * +pm_true_node_synthesized_create(pm_parser_t *parser) { + pm_true_node_t *node = PM_ALLOC_NODE(parser, pm_true_node_t); + + *node = (pm_true_node_t) {{ + .type = PM_TRUE_NODE, + .flags = PM_NODE_FLAG_STATIC_LITERAL, + .location = { .start = parser->start, .end = parser->end } + }}; + + return node; +} + /** * Allocate and initialize a new UndefNode node. */ @@ -6251,6 +6378,27 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm return node; } +/** + * Allocate and initialize a new synthesized while loop. + */ +static pm_while_node_t * +pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_statements_node_t *statements) { + pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t); + + *node = (pm_while_node_t) { + { + .type = PM_WHILE_NODE, + .location = { .start = parser->start, .end = parser->start } + }, + .keyword_loc = { .start = parser->start, .end = parser->start }, + .closing_loc = { .start = parser->start, .end = parser->start }, + .predicate = predicate, + .statements = statements + }; + + return node; +} + /** * Allocate and initialize a new XStringNode node with the given unescaped * string. @@ -18108,6 +18256,80 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc return node; } +/** + * ruby -p, ruby -n, ruby -a, and ruby -l options will mutate the AST. We + * perform that mutation here. + */ +static pm_statements_node_t * +wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) { + if (parser->command_line_p) { + pm_arguments_node_t *arguments = pm_arguments_node_create(parser); + pm_arguments_node_arguments_append( + arguments, + (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2)) + ); + + pm_statements_node_body_append(statements, (pm_node_t *) pm_call_node_fcall_synthesized_create( + parser, + arguments, + pm_parser_constant_id_constant(parser, "print", 5) + )); + } + + if (parser->command_line_n) { + if (parser->command_line_a) { + pm_arguments_node_t *arguments = pm_arguments_node_create(parser); + pm_arguments_node_arguments_append( + arguments, + (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2)) + ); + + pm_global_variable_read_node_t *receiver = pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2)); + pm_call_node_t *call = pm_call_node_call_synthesized_create(parser, (pm_node_t *) receiver, "split", arguments); + + pm_global_variable_write_node_t *write = pm_global_variable_write_node_synthesized_create( + parser, + pm_parser_constant_id_constant(parser, "$F", 2), + (pm_node_t *) call + ); + + pm_statements_node_body_prepend(statements, (pm_node_t *) write); + } + + pm_arguments_node_t *arguments = pm_arguments_node_create(parser); + pm_arguments_node_arguments_append( + arguments, + (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2)) + ); + + if (parser->command_line_l) { + pm_keyword_hash_node_t *keywords = pm_keyword_hash_node_create(parser); + pm_keyword_hash_node_elements_append(keywords, (pm_node_t *) pm_assoc_node_create( + parser, + (pm_node_t *) pm_symbol_node_synthesized_create(parser, "chomp"), + &(pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start }, + (pm_node_t *) pm_true_node_synthesized_create(parser) + )); + + pm_arguments_node_arguments_append(arguments, (pm_node_t *) keywords); + } + + pm_statements_node_t *wrapped_statements = pm_statements_node_create(parser); + pm_statements_node_body_append(wrapped_statements, (pm_node_t *) pm_while_node_synthesized_create( + parser, + (pm_node_t *) pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4)), + statements + )); + + statements = wrapped_statements; + } + + return statements; +} + +/** + * Parse the top-level program node. + */ static pm_node_t * parse_program(pm_parser_t *parser) { // If the current scope is NULL, then we want to push a new top level scope. @@ -18132,6 +18354,12 @@ parse_program(pm_parser_t *parser) { pm_statements_node_location_set(statements, parser->start, parser->start); } + // At the top level, see if we need to wrap the statements in a program + // node with a while loop based on the options. + if (parser->command_line_p || parser->command_line_n) { + statements = wrap_statements(parser, statements); + } + return (pm_node_t *) pm_program_node_create(parser, &locals, statements); } @@ -18189,7 +18417,11 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm .in_keyword_arg = false, .current_param_name = 0, .semantic_token_seen = false, - .frozen_string_literal = false + .frozen_string_literal = false, + .command_line_p = options != NULL && options->command_line_p, + .command_line_n = options != NULL && options->command_line_n, + .command_line_l = options != NULL && options->command_line_l, + .command_line_a = options != NULL && options->command_line_a }; // Initialize the constant pool. We're going to completely guess as to the diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index f9c58c82e12393..7d2a9f58cbf888 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -42,6 +42,18 @@ pm_node_list_append(pm_node_list_t *list, pm_node_t *node) { } } +/** + * Prepend a new node onto the beginning of the node list. + */ +void +pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node) { + if (pm_node_list_grow(list)) { + memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *)); + list->nodes[0] = node; + list->size++; + } +} + /** * Free the internal memory associated with the given node list. */ diff --git a/test/prism/command_line_test.rb b/test/prism/command_line_test.rb new file mode 100644 index 00000000000000..f83110a6129f68 --- /dev/null +++ b/test/prism/command_line_test.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +module Prism + class CommandLineTest < TestCase + def test_command_line_p + program = Prism.parse("1", command_line_p: true).value + statements = program.statements.body + + assert_equal 2, statements.length + assert_kind_of CallNode, statements.last + assert_equal :print, statements.last.name + end + + def test_command_line_n + program = Prism.parse("1", command_line_n: true).value + statements = program.statements.body + + assert_equal 1, statements.length + assert_kind_of WhileNode, statements.first + + predicate = statements.first.predicate + assert_kind_of CallNode, predicate + assert_equal :gets, predicate.name + + arguments = predicate.arguments.arguments + assert_equal 1, arguments.length + assert_equal :$/, arguments.first.name + end + + def test_command_line_a + program = Prism.parse("1", command_line_n: true, command_line_a: true).value + statements = program.statements.body + + assert_equal 1, statements.length + assert_kind_of WhileNode, statements.first + + statement = statements.first.statements.body.first + assert_kind_of GlobalVariableWriteNode, statement + assert_equal :$F, statement.name + end + + def test_command_line_l + program = Prism.parse("1", command_line_n: true, command_line_l: true).value + statements = program.statements.body + + assert_equal 1, statements.length + assert_kind_of WhileNode, statements.first + + predicate = statements.first.predicate + assert_kind_of CallNode, predicate + assert_equal :gets, predicate.name + + arguments = predicate.arguments.arguments + assert_equal 2, arguments.length + assert_equal :$/, arguments.first.name + assert_equal "chomp", arguments.last.elements.first.key.unescaped + end + end +end From 7b56353d97d38719c8dfa0255c9ca46dacd7ffad Mon Sep 17 00:00:00 2001 From: Fable Phippen Date: Mon, 26 Feb 2024 14:24:22 -0500 Subject: [PATCH 117/147] Add a failing test for https://bugs.ruby-lang.org/issues/20305. This bug demonstrates the issue I reported. It passes on commit https://github.com/ruby/ruby/commit/114e71d06280f9c57b9859ee4405ae89a989ddb6 but does not pass on commit (the immediate child of the above commit) https://github.com/ruby/ruby/commit/1d2d25dcadda0764f303183ac091d0c87b432566 --- test/ruby/test_string.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 149c128ed40bbf..8b70bbb46db7ca 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1130,6 +1130,11 @@ def test_grapheme_clusters_memory_leak end; end + def test_byteslice_grapheme_clusters + string = "안녕" + assert_equal(["안"], string.byteslice(0,4).grapheme_clusters) + end + def test_each_line verbose, $VERBOSE = $VERBOSE, nil From 3a04ea2d0379dd8c6623c2d5563e6b4e23986fae Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 Feb 2024 12:20:35 +0900 Subject: [PATCH 118/147] [Bug #20305] Fix matching against an incomplete character When matching against an incomplete character, some `enclen` calls are expected not to exceed the limit, and some are expected to return the required length and then the results are checked if it exceeds. --- regexec.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/regexec.c b/regexec.c index 9e6f503ed03f7f..95332915840e96 100644 --- a/regexec.c +++ b/regexec.c @@ -1943,6 +1943,19 @@ static int string_cmp_ic(OnigEncoding enc, int case_fold_flag, # define ABSENT_END_POS end #endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */ +int onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); + +static inline int +enclen_approx(OnigEncoding enc, const OnigUChar* p, const OnigUChar* e) +{ + if (enc->max_enc_len == enc->min_enc_len) { + return (p < e ? enc->min_enc_len : 0); + } + else { + return onigenc_mbclen_approximate(p, e, enc); + } +} + #ifdef USE_CAPTURE_HISTORY static int @@ -2923,7 +2936,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, int mb_len; DATA_ENSURE(1); - mb_len = enclen(encode, s, end); + mb_len = enclen_approx(encode, s, end); DATA_ENSURE(mb_len); ss = s; s += mb_len; @@ -3028,7 +3041,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, CASE(OP_ANYCHAR) MOP_IN(OP_ANYCHAR); DATA_ENSURE(1); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail; s += n; @@ -3037,7 +3050,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, CASE(OP_ANYCHAR_ML) MOP_IN(OP_ANYCHAR_ML); DATA_ENSURE(1); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); DATA_ENSURE(n); s += n; MOP_OUT; @@ -3047,7 +3060,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, while (DATA_ENSURE_CHECK1) { CHECK_MATCH_CACHE; STACK_PUSH_ALT(p, s, sprev, pkeep); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail; sprev = s; @@ -3060,7 +3073,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, while (DATA_ENSURE_CHECK1) { CHECK_MATCH_CACHE; STACK_PUSH_ALT(p, s, sprev, pkeep); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); if (n > 1) { DATA_ENSURE(n); sprev = s; @@ -3086,7 +3099,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, msa->num_fails++; #endif } - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail; sprev = s; @@ -3108,7 +3121,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, msa->num_fails++; #endif } - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); if (n > 1) { DATA_ENSURE(n); sprev = s; @@ -3131,7 +3144,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, if (scv) goto fail; STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail; sprev = s; @@ -3149,7 +3162,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, if (scv) goto fail; STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep); - n = enclen(encode, s, end); + n = enclen_approx(encode, s, end); if (n > 1) { DATA_ENSURE(n); sprev = s; @@ -3491,7 +3504,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, DATA_ENSURE(n); sprev = s; STRING_CMP(pstart, s, n); - while (sprev + (len = enclen(encode, sprev, end)) < s) + while (sprev + (len = enclen_approx(encode, sprev, end)) < s) sprev += len; MOP_OUT; @@ -3522,7 +3535,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, DATA_ENSURE(n); sprev = s; STRING_CMP_IC(case_fold_flag, pstart, &s, n, end); - while (sprev + (len = enclen(encode, sprev, end)) < s) + while (sprev + (len = enclen_approx(encode, sprev, end)) < s) sprev += len; MOP_OUT; @@ -3557,7 +3570,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, STRING_CMP_VALUE(pstart, swork, n, is_fail); if (is_fail) continue; s = swork; - while (sprev + (len = enclen(encode, sprev, end)) < s) + while (sprev + (len = enclen_approx(encode, sprev, end)) < s) sprev += len; p += (SIZE_MEMNUM * (tlen - i - 1)); From d50f9ca2dd416d92152cd958b5f39496088481b0 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Tue, 27 Feb 2024 14:19:15 +0900 Subject: [PATCH 119/147] [Bug #20302] Multiple refinements cannot be applied to the same module In the following code, the iclass tree of refinements in cref should be -> -> Kernel. However, the iclass tree was broken because of code for included modules of refinements in rb_using_refinement(). Refinement#include is now removed, so this commit removes such unnecessary code. ```ruby module M1 refine(Kernel) do def f1 = :f1 end end module M2 refine(Kernel) do def f2 = :f2 end end class Foo using M1 using M2 def test p f2 #=> :f2 p f1 # expected => :f1 # actual => undefined local variable or method 'f1' for an instance of Foo end end Foo.new.test ``` --- eval.c | 6 ------ test/ruby/test_refinement.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/eval.c b/eval.c index a330b9c8bcd254..0d74de483a1461 100644 --- a/eval.c +++ b/eval.c @@ -1276,12 +1276,6 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module) RCLASS_M_TBL(c) = RCLASS_M_TBL(module); - module = RCLASS_SUPER(module); - while (module && module != klass) { - c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c))); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); - module = RCLASS_SUPER(module); - } rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass); } diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 826616eb095b52..cb55627e2c8c42 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -2672,6 +2672,35 @@ def foo = :v2 # invalidate assert_equal(:v2, obj.cached_foo_callsite) end + # [Bug #20302] + def test_multiple_refinements_for_same_module + assert_in_out_err([], <<-INPUT, %w(:f2 :f1), []) + module M1 + refine(Kernel) do + def f1 = :f1 + end + end + + module M2 + refine(Kernel) do + def f2 = :f2 + end + end + + class Foo + using M1 + using M2 + + def test + p f2 + p f1 + end + end + + Foo.new.test + INPUT + end + private def eval_using(mod, s) From d7730d3a0bd683b4d1c6f85763de7f0db7b0acf8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 Feb 2024 19:40:39 +0900 Subject: [PATCH 120/147] Constify `literal_type` unless universal parser --- parse.y | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parse.y b/parse.y index 0d993add2cb8e2..de90ee797ff058 100644 --- a/parse.y +++ b/parse.y @@ -15072,6 +15072,9 @@ nd_value(struct parser_params *p, NODE *node) void rb_parser_warn_duplicate_keys(struct parser_params *p, NODE *hash) { +#ifndef UNIVERSAL_PARSER + static const +#endif struct st_hash_type literal_type = { literal_cmp, literal_hash, From 5efe386c89537d86d5a267843ac5da83083baaf5 Mon Sep 17 00:00:00 2001 From: Alexander Ross Date: Tue, 27 Feb 2024 12:19:02 +0100 Subject: [PATCH 121/147] [DOC] Fix typo in GC documentation The documentation for GC.start was incorrect. It said that the `immediate_sweep` keyword argument would defer sweeping when set to `true`, but it should have said that it would defer sweeping when set to `false`. The commit will also fix the typo "immedate_sweep" to "immediate_sweep". --- gc.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gc.rb b/gc.rb index c9c985b994a839..880aa464753697 100644 --- a/gc.rb +++ b/gc.rb @@ -26,10 +26,10 @@ module GC # 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 + # The +immediate_sweep+ keyword argument determines whether or not to defer + # sweeping (using lazy sweep). When set to +false+, 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 + # not be completed during this method call. When set to +true+, sweeping is # completed during the call to this method. # # Note: These keyword arguments are implementation and version dependent. They From 9ba53cb6886fcecf288d9313720987df389aa46c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 15:33:50 -0500 Subject: [PATCH 122/147] Simplify is_live_object --- gc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/gc.c b/gc.c index c65ef5cb9615d1..58e79e5bc0b8dc 100644 --- a/gc.c +++ b/gc.c @@ -4406,12 +4406,7 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr) break; } - if (!is_garbage_object(objspace, ptr)) { - return TRUE; - } - else { - return FALSE; - } + return !is_garbage_object(objspace, ptr); } static inline int From 2396b7a62fc12ef70933872667020b3784cb9e2e Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 15:34:11 -0500 Subject: [PATCH 123/147] Change is_live_object to return a bool --- gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc.c b/gc.c index 58e79e5bc0b8dc..8fdf96503a566c 100644 --- a/gc.c +++ b/gc.c @@ -4394,7 +4394,7 @@ is_garbage_object(rb_objspace_t *objspace, VALUE ptr) } } -static inline int +static inline bool is_live_object(rb_objspace_t *objspace, VALUE ptr) { switch (BUILTIN_TYPE(ptr)) { From fc36882713c7f86dcbec84c996b09a9c79a2d71f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 27 Feb 2024 09:44:13 -0500 Subject: [PATCH 124/147] [ruby/prism] Ensure symbol nodes not in interpolated symbol https://github.com/ruby/prism/commit/e1a9a1d478 --- prism/prism.c | 15 +++++++++++---- test/prism/snapshots/spanning_heredoc.txt | 6 +++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 0cedf924e439d2..7c41b1670e3b4a 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -16523,15 +16523,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string); } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) { - // If we hit string content and the current node is a string node, + // If we hit string content and the current node is a symbol node, // then we need to convert the current node into an interpolated // string and add the string content to the list of child nodes. - pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing); + pm_symbol_node_t *cast = (pm_symbol_node_t *) current; + pm_token_t bounds = not_provided(parser); + + pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = cast->value_loc.start, .end = cast->value_loc.end }; + pm_node_t *first_string = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped); + pm_node_t *second_string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing); parser_lex(parser); pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing); - pm_interpolated_symbol_node_append(interpolated, current); - pm_interpolated_symbol_node_append(interpolated, string); + pm_interpolated_symbol_node_append(interpolated, first_string); + pm_interpolated_symbol_node_append(interpolated, second_string); + + free(current); current = (pm_node_t *) interpolated; } else { assert(false && "unreachable"); diff --git a/test/prism/snapshots/spanning_heredoc.txt b/test/prism/snapshots/spanning_heredoc.txt index da930499d6ede8..90297d2282c753 100644 --- a/test/prism/snapshots/spanning_heredoc.txt +++ b/test/prism/snapshots/spanning_heredoc.txt @@ -298,10 +298,10 @@ │ │ │ └── @ InterpolatedSymbolNode (location: (48,12)-(48,14)) │ │ │ ├── opening_loc: ∅ │ │ │ ├── parts: (length: 2) - │ │ │ │ ├── @ SymbolNode (location: (48,12)-(48,14)) - │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ ├── @ StringNode (location: (48,12)-(48,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (48,12)-(48,14) = "p\\" + │ │ │ │ │ ├── content_loc: (48,12)-(48,14) = "p\\" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "p\n" │ │ │ │ └── @ StringNode (location: (48,12)-(48,14)) From f67c9d001aefef26584b2d64c913240f0459f90b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 27 Feb 2024 10:52:56 -0500 Subject: [PATCH 125/147] [ruby/prism] Switch invalid _1 targeting even on syntax error https://github.com/ruby/prism/commit/40dec909b7 --- prism/prism.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 7c41b1670e3b4a..0c24681a5bffbe 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11414,12 +11414,10 @@ parse_target(pm_parser_t *parser, pm_node_t *target) { target->type = PM_GLOBAL_VARIABLE_TARGET_NODE; return target; case PM_LOCAL_VARIABLE_READ_NODE: - if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) { - PM_PARSER_ERR_NODE_FORMAT(parser, target, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->location.start); - } else { - assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t)); - target->type = PM_LOCAL_VARIABLE_TARGET_NODE; - } + pm_refute_numbered_parameter(parser, target->location.start, target->location.end); + + assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t)); + target->type = PM_LOCAL_VARIABLE_TARGET_NODE; return target; case PM_INSTANCE_VARIABLE_READ_NODE: From 1f740cd1115fd96d5da7e7c08223de5396e8b5f1 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 15:47:48 -0500 Subject: [PATCH 126/147] Remove is_swept_object The name is misleading, as it seems like the function checks whether the object is swept or not. But the function only checks whether the page is before or after sweeping. --- gc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/gc.c b/gc.c index 8fdf96503a566c..cb5dbaee59689e 100644 --- a/gc.c +++ b/gc.c @@ -4372,19 +4372,12 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) ATOMIC_SET(finalizing, 0); } -static inline int -is_swept_object(VALUE ptr) -{ - struct heap_page *page = GET_HEAP_PAGE(ptr); - return page->flags.before_sweep ? FALSE : TRUE; -} - /* garbage objects will be collected soon. */ static inline int is_garbage_object(rb_objspace_t *objspace, VALUE ptr) { if (!is_lazy_sweeping(objspace) || - is_swept_object(ptr) || + !GET_HEAP_PAGE(ptr)->flags.before_sweep || MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) { return FALSE; @@ -13570,7 +13563,7 @@ rb_gcdebug_print_obj_condition(VALUE obj) if (is_lazy_sweeping(objspace)) { fprintf(stderr, "lazy sweeping?: true\n"); - fprintf(stderr, "swept?: %s\n", is_swept_object(obj) ? "done" : "not yet"); + fprintf(stderr, "page swept?: %s\n", GET_HEAP_PAGE(ptr)->flags.before_sweep ? "false" : "true"); } else { fprintf(stderr, "lazy sweeping?: false\n"); From 11f121364ab0b113bcc721ed375a321148e0e8f5 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 27 Feb 2024 12:50:38 -0500 Subject: [PATCH 127/147] YJIT: Support splat with C methods with -1 arity Usually we deal with splats by speculating that they're of a specific size. In this case, the C method takes a pointer and a length, so we can support changing sizes just fine. --- bootstraptest/test_yjit.rb | 24 +++++++++++++ yjit.c | 45 +++++++++++++++++++++++ yjit/bindgen/src/main.rs | 2 ++ yjit/src/codegen.rs | 65 ++++++++++++++++++++++++++-------- yjit/src/cruby_bindings.inc.rs | 9 +++++ yjit/src/stats.rs | 3 +- 6 files changed, 133 insertions(+), 15 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index a2c98c01c939aa..1d98b92d3a425a 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4634,3 +4634,27 @@ def splat_nil_kw_splat(args) = identity(*args, **nil) empty = [] [1.abs(*empty), 1.abs(**nil), 1.bit_length(*empty, **nil)] } + +# splat into C methods with -1 arity +assert_equal '[[1, 2, 3], [0, 2, 3], [1, 2, 3], [2, 2, 3], [], [], [{}]]', %q{ + class Foo < Array + def push(args) = super(1, *args) + end + + def test_cfunc_vargs_splat(sub_instance, array_class, empty_kw_hash) + splat = [2, 3] + kw_splat = [empty_kw_hash] + [ + sub_instance.push(splat), + array_class[0, *splat, **nil], + array_class[1, *splat, &nil], + array_class[2, *splat, **nil, &nil], + array_class.send(:[], *kw_splat), + # kw_splat disables keywords hash handling + array_class[*kw_splat], + array_class[*kw_splat, **nil], + ] + end + + test_cfunc_vargs_splat(Foo.new, Array, Hash.ruby2_keywords_hash({})) +} diff --git a/yjit.c b/yjit.c index 207974073b0f68..8632361699dde8 100644 --- a/yjit.c +++ b/yjit.c @@ -890,6 +890,51 @@ rb_yjit_ruby2_keywords_splat_p(VALUE obj) return FL_TEST_RAW(last, RHASH_PASS_AS_KEYWORDS); } +// Checks to establish preconditions for rb_yjit_splat_varg_cfunc() +VALUE +rb_yjit_splat_varg_checks(VALUE *sp, VALUE splat_array, rb_control_frame_t *cfp) +{ + // We inserted a T_ARRAY guard before this call + long len = RARRAY_LEN(splat_array); + + // Large splat arrays need a separate allocation + if (len < 0 || len > VM_ARGC_STACK_MAX) return Qfalse; + + // Would we overflow if we put the contents of the array onto the stack? + if (sp + len > (VALUE *)(cfp - 2)) return Qfalse; + + return Qtrue; +} + +// Push array elements to the stack for a C method that has a variable number +// of parameters. Returns the number of arguments the splat array contributes. +int +rb_yjit_splat_varg_cfunc(VALUE *stack_splat_array, bool sole_splat) +{ + VALUE splat_array = *stack_splat_array; + int len; + + // We already checked that length fits in `int` + RUBY_ASSERT(RB_TYPE_P(splat_array, T_ARRAY)); + len = (int)RARRAY_LEN(splat_array); + + // If this is a splat call without any keyword arguments, exclude the + // ruby2_keywords hash if it's empty + if (sole_splat && len > 0) { + VALUE last_hash = RARRAY_AREF(splat_array, len - 1); + if (RB_TYPE_P(last_hash, T_HASH) && + FL_TEST_RAW(last_hash, RHASH_PASS_AS_KEYWORDS) && + RHASH_EMPTY_P(last_hash)) { + len--; + } + } + + // Push the contents of the array onto the stack + MEMCPY(stack_splat_array, RARRAY_CONST_PTR(splat_array), VALUE, len); + + return len; +} + // Print the Ruby source location of some ISEQ for debugging purposes void rb_yjit_dump_iseq_loc(const rb_iseq_t *iseq, uint32_t insn_idx) diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index a1b8cf3a75dd0e..c58df7c3773b90 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -460,6 +460,8 @@ fn main() { .allowlist_function("rb_vm_base_ptr") .allowlist_function("rb_ec_stack_check") .allowlist_function("rb_vm_top_self") + .allowlist_function("rb_yjit_splat_varg_checks") + .allowlist_function("rb_yjit_splat_varg_cfunc") // We define VALUE manually, don't import it .blocklist_type("VALUE") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 41c7adae2c658d..2e946441f15100 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6140,18 +6140,16 @@ fn gen_send_cfunc( let cfunc_argc = unsafe { get_mct_argc(cfunc) }; let mut argc = argc; + // Splat call to a C method that takes `VALUE *` and `len` + let variable_splat = flags & VM_CALL_ARGS_SPLAT != 0 && cfunc_argc == -1; + let block_arg = flags & VM_CALL_ARGS_BLOCKARG != 0; + // If the function expects a Ruby array of arguments if cfunc_argc < 0 && cfunc_argc != -1 { gen_counter_incr(asm, Counter::send_cfunc_ruby_array_varg); return None; } - // We aren't handling a vararg cfuncs with splat currently. - if flags & VM_CALL_ARGS_SPLAT != 0 && cfunc_argc == -1 { - gen_counter_incr(asm, Counter::send_args_splat_cfunc_var_args); - return None; - } - exit_if_kwsplat_non_nil(asm, flags, Counter::send_cfunc_kw_splat_non_nil)?; let kw_splat = flags & VM_CALL_KW_SPLAT != 0; @@ -6217,6 +6215,18 @@ fn gen_send_cfunc( asm.cmp(CFP, stack_limit); asm.jbe(Target::side_exit(Counter::guard_send_se_cf_overflow)); + // Guard for variable length splat call before any modifications to the stack + if variable_splat { + let splat_array = asm.stack_opnd(i32::from(kw_splat) + i32::from(block_arg)); + guard_object_is_array(asm, splat_array, splat_array.into(), Counter::guard_send_splat_not_array); + + asm_comment!(asm, "guard variable length splat call servicable"); + let sp = asm.ctx.sp_opnd(0); + let proceed = asm.ccall(rb_yjit_splat_varg_checks as _, vec![sp, splat_array, CFP]); + asm.cmp(proceed, Qfalse.into()); + asm.je(Target::side_exit(Counter::guard_send_cfunc_bad_splat_vargs)); + } + // Number of args which will be passed through to the callee // This is adjusted by the kwargs being combined into a hash. let mut passed_argc = if kw_arg.is_null() { @@ -6242,7 +6252,6 @@ fn gen_send_cfunc( return None; } - let block_arg = flags & VM_CALL_ARGS_BLOCKARG != 0; let block_arg_type = if block_arg { Some(asm.ctx.get_opnd_type(StackOpnd(0))) } else { @@ -6287,9 +6296,9 @@ fn gen_send_cfunc( argc -= 1; } - // push_splat_args does stack manipulation so we can no longer side exit - if flags & VM_CALL_ARGS_SPLAT != 0 { - assert!(cfunc_argc >= 0); + // Splat handling when C method takes a static number of arguments. + // push_splat_args() does stack manipulation so we can no longer side exit + if flags & VM_CALL_ARGS_SPLAT != 0 && cfunc_argc >= 0 { let required_args : u32 = (cfunc_argc as u32).saturating_sub(argc as u32 - 1); // + 1 because we pass self if required_args + 1 >= C_ARG_OPNDS.len() as u32 { @@ -6312,15 +6321,34 @@ fn gen_send_cfunc( handle_opt_send_shift_stack(asm, argc); } + // Push a dynamic number of items from the splat array to the stack when calling a vargs method + let dynamic_splat_size = if variable_splat { + asm_comment!(asm, "variable length splat"); + let just_splat = usize::from(!kw_splat && kw_arg.is_null()).into(); + let stack_splat_array = asm.lea(asm.stack_opnd(0)); + Some(asm.ccall(rb_yjit_splat_varg_cfunc as _, vec![stack_splat_array, just_splat])) + } else { + None + }; + // Points to the receiver operand on the stack let recv = asm.stack_opnd(argc); // Store incremented PC into current control frame in case callee raises. jit_save_pc(jit, asm); - // Increment the stack pointer by 3 (in the callee) - // sp += 3 - let sp = asm.lea(asm.ctx.sp_opnd(SIZEOF_VALUE_I32 * 3)); + // Find callee's SP with space for metadata. + // Usually sp+3. + let sp = if let Some(splat_size) = dynamic_splat_size { + // Compute the callee's SP at runtime in case we accept a variable size for the splat array + const _: () = assert!(SIZEOF_VALUE == 8, "opting for a shift since mul on A64 takes no immediates"); + let splat_size_bytes = asm.lshift(splat_size, 3usize.into()); + // 3 items for method metadata, minus one to remove the splat array + let static_stack_top = asm.lea(asm.ctx.sp_opnd(SIZEOF_VALUE_I32 * 2)); + asm.add(static_stack_top, splat_size_bytes) + } else { + asm.lea(asm.ctx.sp_opnd(SIZEOF_VALUE_I32 * 3)) + }; let specval = if block_arg_type == Some(Type::BlockParamProxy) { SpecVal::BlockHandler(Some(BlockHandler::BlockParamProxy)) @@ -6382,8 +6410,17 @@ fn gen_send_cfunc( else if cfunc_argc == -1 { // The method gets a pointer to the first argument // rb_f_puts(int argc, VALUE *argv, VALUE recv) + + let passed_argc_opnd = if let Some(splat_size) = dynamic_splat_size { + // The final argc is the size of the splat, minus one for the splat array itself + asm.add(splat_size, (passed_argc - 1).into()) + } else { + // Without a splat, passed_argc is static + Opnd::Imm(passed_argc.into()) + }; + vec![ - Opnd::Imm(passed_argc.into()), + passed_argc_opnd, asm.lea(asm.ctx.sp_opnd(-argc * SIZEOF_VALUE_I32)), asm.stack_opnd(argc), ] diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 3ba351cea9dbd7..b131b62bfd1b1c 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1194,6 +1194,15 @@ extern "C" { pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize; + pub fn rb_yjit_splat_varg_checks( + sp: *mut VALUE, + splat_array: VALUE, + cfp: *mut rb_control_frame_t, + ) -> VALUE; + pub fn rb_yjit_splat_varg_cfunc( + stack_splat_array: *mut VALUE, + sole_splat: bool, + ) -> ::std::os::raw::c_int; pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char; pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 6cdf1d0616a2e4..d60e35b9dd22d6 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -386,7 +386,6 @@ make_counters! { send_args_splat_aref, send_args_splat_aset, send_args_splat_opt_call, - send_args_splat_cfunc_var_args, send_iseq_splat_arity_error, send_splat_too_long, send_send_wrong_args, @@ -444,6 +443,8 @@ make_counters! { guard_send_not_string, guard_send_respond_to_mid_mismatch, + guard_send_cfunc_bad_splat_vargs, + guard_invokesuper_me_changed, guard_invokeblock_tag_changed, From e14a68a1bf2fa1350deae169eb9a90e95f839b3c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 27 Feb 2024 12:42:07 -0500 Subject: [PATCH 128/147] [ruby/prism] Disallow it implicit in eval https://github.com/ruby/prism/commit/6fcb8fc974 --- prism/prism.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 0c24681a5bffbe..d6a8d506805ed3 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -6668,6 +6668,7 @@ pm_node_check_it(pm_parser_t *parser, pm_node_t *node) { if ( (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0) && !parser->current_scope->closed && + (parser->current_scope->numbered_parameters != PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED) && pm_node_is_it(parser, node) ) { pm_local_variable_read_node_t *read = pm_local_variable_read_node_create_it(parser, &parser->previous); @@ -14299,7 +14300,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { pm_node_t *variable = (pm_node_t *) parse_variable(parser); if (variable == NULL) { - if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0 && pm_token_is_it(parser->previous.start, parser->previous.end)) { + if ( + (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0) && + !parser->current_scope->closed && + (parser->current_scope->numbered_parameters != PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED) && + pm_token_is_it(parser->previous.start, parser->previous.end) + ) { pm_local_variable_read_node_t *read = pm_local_variable_read_node_create_it(parser, &parser->previous); if (read == NULL) read = pm_local_variable_read_node_create(parser, &parser->previous, 0); variable = (pm_node_t *) read; From 3c44f6da6c8dab09b7724e5456eaad0d1e3cb12e Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 27 Feb 2024 12:27:46 -0500 Subject: [PATCH 129/147] Simplify is_garbage_object --- gc.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/gc.c b/gc.c index cb5dbaee59689e..e7368544ce46cc 100644 --- a/gc.c +++ b/gc.c @@ -4376,15 +4376,8 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) static inline int is_garbage_object(rb_objspace_t *objspace, VALUE ptr) { - if (!is_lazy_sweeping(objspace) || - !GET_HEAP_PAGE(ptr)->flags.before_sweep || - MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr)) { - - return FALSE; - } - else { - return TRUE; - } + return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep && + !MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr); } static inline bool From 08731182b8b1533e3a98e107fdd98ec7dc3194eb Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 27 Feb 2024 12:28:26 -0500 Subject: [PATCH 130/147] Change is_garbage_object to return a bool --- gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc.c b/gc.c index e7368544ce46cc..d598a7deaceef6 100644 --- a/gc.c +++ b/gc.c @@ -4373,7 +4373,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) } /* garbage objects will be collected soon. */ -static inline int +static inline bool is_garbage_object(rb_objspace_t *objspace, VALUE ptr) { return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep && From 7c4bf61a35a89a10ff2ef9214a27bd478241027e Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sun, 25 Feb 2024 16:16:12 +0900 Subject: [PATCH 131/147] [ruby/prism] Follow RuboCop's parser engine support With the introduction of `Prism::Translation::Parser` to RuboCop (RuboCop AST), the number of arguments for `RuboCop::AST::ProcessedSource#parser_class` internal API will be changed: https://github.com/rubocop/rubocop-ast/pull/277 ## Before As a result, the following error will occur starting from the next release of RuboCop AST (< 1.30.0) : ```console $ bundle exec ruby -rrubocop/ast -rprism -rprism/translation/parser/rubocop -ve \ "p RuboCop::AST::ProcessedSource.new('42', 80_82_73_83_77.33).ast" ruby 3.3.0 (2023-12-25 revision https://github.com/ruby/prism/commit/5124f9ac75) [x86_64-darwin22] /Users/koic/src/github.com/ruby/prism/lib/prism/translation/parser/rubocop.rb:25:in `parser_class': wrong number of arguments (given 2, expected 1) (ArgumentError) from /Users/koic/src/github.com/rubocop/rubocop-ast/lib/rubocop/ast/processed_source.rb:309:in `create_parser' from /Users/koic/src/github.com/rubocop/rubocop-ast/lib/rubocop/ast/processed_source.rb:219:in `parse' from /Users/koic/src/github.com/rubocop/rubocop-ast/lib/rubocop/ast/processed_source.rb:47:in `initialize' from -e:1:in `new' from -e:1:in `
' ``` ## After This PR prevents the above error by updating the monkey patch to support the new argument: ```console $ bundle exec ruby -rrubocop/ast -rprism -rprism/translation/parser/rubocop -ve \ "p RuboCop::AST::ProcessedSource.new('42', 80_82_73_83_77.33).ast" ruby 3.3.0 (2023-12-25 revision https://github.com/ruby/prism/commit/5124f9ac75) [x86_64-darwin22] s(:int, 42) ``` Moreover, to ensure compatibility with the existing RuboCop AST, conditional logic has been implemented to maintain backward compatibility. https://github.com/ruby/prism/commit/8a6909f4d5 --- lib/prism/translation/parser/rubocop.rb | 39 ++++++++++++++++++------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/prism/translation/parser/rubocop.rb b/lib/prism/translation/parser/rubocop.rb index 69138f74f3fb06..c791ba74a28a31 100644 --- a/lib/prism/translation/parser/rubocop.rb +++ b/lib/prism/translation/parser/rubocop.rb @@ -20,17 +20,34 @@ class Parser # This module gets prepended into RuboCop::AST::ProcessedSource. module ProcessedSource - # Redefine parser_class so that we can inject the prism parser into the - # list of known parsers. - def parser_class(ruby_version) - if ruby_version == Prism::Translation::Parser::VERSION_3_3 - require "prism/translation/parser33" - Prism::Translation::Parser33 - elsif ruby_version == Prism::Translation::Parser::VERSION_3_4 - require "prism/translation/parser34" - Prism::Translation::Parser34 - else - super + # This condition is compatible with rubocop-ast versions up to 1.30.0. + if RuboCop::AST::ProcessedSource.instance_method(:parser_class).arity == 1 + # Redefine parser_class so that we can inject the prism parser into the + # list of known parsers. + def parser_class(ruby_version) + if ruby_version == Prism::Translation::Parser::VERSION_3_3 + require "prism/translation/parser33" + Prism::Translation::Parser33 + elsif ruby_version == Prism::Translation::Parser::VERSION_3_4 + require "prism/translation/parser34" + Prism::Translation::Parser34 + else + super + end + end + else + # Redefine parser_class so that we can inject the prism parser into the + # list of known parsers. + def parser_class(ruby_version, _parser_engine) + if ruby_version == Prism::Translation::Parser::VERSION_3_3 + require "prism/translation/parser33" + Prism::Translation::Parser33 + elsif ruby_version == Prism::Translation::Parser::VERSION_3_4 + require "prism/translation/parser34" + Prism::Translation::Parser34 + else + super + end end end end From edc7b73fc4755bb91ea16d1513993fbce5a6e244 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 27 Feb 2024 14:36:19 -0500 Subject: [PATCH 132/147] Remove pointer check in moved_or_living_object_strictly_p We don't need to check that the object is pointer to the GC heap in moved_or_living_object_strictly_p because it is called during reference updating, which does not free pages so it can never point to an object that is not on the GC heap. --- imemo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imemo.c b/imemo.c index 9bda0390071d06..66428f39b40f30 100644 --- a/imemo.c +++ b/imemo.c @@ -215,9 +215,7 @@ rb_cc_table_mark(VALUE klass) static bool moved_or_living_object_strictly_p(VALUE obj) { - return obj && - rb_gc_is_ptr_to_obj((void *)obj) && - (rb_objspace_markable_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED); + return obj && (rb_objspace_markable_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED); } static void From 3668118572c8d1f8faa95034883b52aa9d05c5c4 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 27 Feb 2024 14:02:24 -0800 Subject: [PATCH 133/147] [DOC] Stop discouraging the use of Array#each (#10119) --- doc/yjit/yjit.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index 63588c286923b3..8aab1aed22f79c 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -268,8 +268,6 @@ This section contains tips on writing Ruby code that will run as fast as possibl - Avoid classes that wrap objects if you can - Avoid methods that just call another method, trivial one-liner methods - Try to write code so that the same variables always have the same type -- Use `while` loops if you can, instead of C methods like `Array#each` - - This is not idiomatic Ruby, but could help in hot methods - CRuby method calls are costly. Avoid things such as methods that only return a value from a hash or return a constant. You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code. From 95e55e9ae4a446a62db21e2ea91c54d20fbdcbdc Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 28 Feb 2024 11:08:49 +0900 Subject: [PATCH 134/147] Also ignore git ls-files command with IO.popen style for tmpdir.gemspec and tempfile.gemspec --- test/ruby/test_default_gems.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb index d8e8226253a146..935a3104386325 100644 --- a/test/ruby/test_default_gems.rb +++ b/test/ruby/test_default_gems.rb @@ -8,6 +8,7 @@ def self.load(file) # - `git ls-files` is useless under ruby's repository # - `2>/dev/null` works only on Unix-like platforms code.gsub!(/`git.*?`/, '""') + code.gsub!(/\[git.*?\]/, '[]') eval(code, binding, file) end From e8e2415bb32c7e9f2a55d218a97cb5f9474b2898 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 27 Feb 2024 15:09:18 -0500 Subject: [PATCH 135/147] Use RB_SPECIAL_CONST_P instead of rb_special_const_p rb_special_const_p returns a VALUE (Qtrue or Qfalse), so we shouldn't assume that Qfalse is 0. We should instead use RB_SPECIAL_CONST_P. --- gc.c | 2 +- marshal.c | 2 +- vm.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gc.c b/gc.c index d598a7deaceef6..df61246d4616b9 100644 --- a/gc.c +++ b/gc.c @@ -4398,7 +4398,7 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr) static inline int is_markable_object(VALUE obj) { - if (rb_special_const_p(obj)) return FALSE; /* special const is not markable */ + if (RB_SPECIAL_CONST_P(obj)) return FALSE; /* special const is not markable */ check_rvalue_consistency(obj); return TRUE; } diff --git a/marshal.c b/marshal.c index 9fc4b0b80e7304..dabbdcd663eb1a 100644 --- a/marshal.c +++ b/marshal.c @@ -1889,7 +1889,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ goto type_hash; } v = r_object_for(arg, partial, 0, extmod, type); - if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) { + if (RB_SPECIAL_CONST_P(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) { goto format_error; } if (RB_TYPE_P(v, T_MODULE) || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) { diff --git a/vm.c b/vm.c index 3ceaef1a4bf83d..68b2cfc58af19b 100644 --- a/vm.c +++ b/vm.c @@ -2922,7 +2922,7 @@ rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx) VALUE *p = ec->vm_stack; VALUE *sp = ec->cfp->sp; while (p < sp) { - if (!rb_special_const_p(*p)) { + if (!RB_SPECIAL_CONST_P(*p)) { cb(*p, ctx); } p++; From 47b46fd98c71732400d53805f63ab988b28fa651 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 28 Feb 2024 11:14:44 +0900 Subject: [PATCH 136/147] Use dummy command for IO.popen --- test/ruby/test_default_gems.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb index 935a3104386325..71371b46c3b784 100644 --- a/test/ruby/test_default_gems.rb +++ b/test/ruby/test_default_gems.rb @@ -8,7 +8,7 @@ def self.load(file) # - `git ls-files` is useless under ruby's repository # - `2>/dev/null` works only on Unix-like platforms code.gsub!(/`git.*?`/, '""') - code.gsub!(/\[git.*?\]/, '[]') + code.gsub!(/\[git.*?\]/, '[echo]') eval(code, binding, file) end From fe0b704df5553bdd59e90650ffbbfac785a2e48a Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sat, 24 Feb 2024 14:45:05 +1100 Subject: [PATCH 137/147] Skip assert_no_memory_leak when ASAN is enabled ASAN greatly increases the memory footprint of Ruby, so these static thresholds are not appropriate. There's no real need to run these tests under ASAN. [Bug #20274] --- ext/-test-/asan/asan.c | 24 ++++++++++++++++++++++++ ext/-test-/asan/extconf.rb | 2 ++ tool/lib/core_assertions.rb | 8 ++++++++ 3 files changed, 34 insertions(+) create mode 100644 ext/-test-/asan/asan.c create mode 100644 ext/-test-/asan/extconf.rb diff --git a/ext/-test-/asan/asan.c b/ext/-test-/asan/asan.c new file mode 100644 index 00000000000000..45b6253fdac8c8 --- /dev/null +++ b/ext/-test-/asan/asan.c @@ -0,0 +1,24 @@ +#include "ruby/ruby.h" + +static VALUE +asan_enabled_p(VALUE self) +{ +#if defined(__has_feature) + /* clang uses __has_feature for determining asan */ + return __has_feature(address_sanitizer) ? Qtrue : Qfalse; +#elif defined(__SANITIZE_ADDRESS__) + /* GCC sets __SANITIZE_ADDRESS__ for determining asan */ + return Qtrue; +#else + return Qfalse; +#endif +} + +void +Init_asan(void) +{ + VALUE m = rb_define_module("Test"); + VALUE c = rb_define_class_under(m, "ASAN", rb_cObject); + rb_define_singleton_method(c, "enabled?", asan_enabled_p, 0); +} + diff --git a/ext/-test-/asan/extconf.rb b/ext/-test-/asan/extconf.rb new file mode 100644 index 00000000000000..ec02742b8145e4 --- /dev/null +++ b/ext/-test-/asan/extconf.rb @@ -0,0 +1,2 @@ +require 'mkmf' +create_makefile('-test-/asan') diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index 358e7d9551aedd..b456a55b340eb7 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -74,6 +74,11 @@ def message msg = nil, ending = nil, &default module CoreAssertions require_relative 'envutil' require 'pp' + begin + require '-test-/asan' + rescue LoadError + end + nil.pretty_inspect def mu_pp(obj) #:nodoc: @@ -152,6 +157,9 @@ def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: fal pend 'assert_no_memory_leak may consider RJIT memory usage as leak' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # For previous versions which implemented MJIT pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + # ASAN has the same problem - its shadow memory greatly increases memory usage + # (plus asan has better ways to detect memory leaks than this assertion) + pend 'assert_no_memory_leak may consider ASAN memory usage as leak' if defined?(Test::ASAN) && Test::ASAN.enabled? require_relative 'memory_status' raise Test::Unit::PendedError, "unsupported platform" unless defined?(Memory::Status) From 75a4aa2052d5b34c1e6bb8085426e50ee627d89a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 28 Feb 2024 12:49:03 +0900 Subject: [PATCH 138/147] Support file listing with IO.poepn style --- tool/rbinstall.rb | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb index 16d264adf732af..7905f34f090577 100755 --- a/tool/rbinstall.rb +++ b/tool/rbinstall.rb @@ -958,17 +958,20 @@ def ensure_writable_dir(dir) def load_gemspec(file, base = nil) file = File.realpath(file) code = File.read(file, encoding: "utf-8:-") + + files = [] + Dir.glob("**/*", File::FNM_DOTMATCH, base: base) do |n| + case File.basename(n); when ".", ".."; next; end + next if File.directory?(File.join(base, n)) + files << n.dump + end if base code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m) do - files = [] - if base - Dir.glob("**/*", File::FNM_DOTMATCH, base: base) do |n| - case File.basename(n); when ".", ".."; next; end - next if File.directory?(File.join(base, n)) - files << n.dump - end - end "[" + files.join(", ") + "]" end + code.gsub!(/IO\.popen\(.*git.*?\)/) do + "[" + files.join(", ") + "].each" + end + spec = eval(code, binding, file) unless Gem::Specification === spec raise TypeError, "[#{file}] isn't a Gem::Specification (#{spec.class} instead)." From 05387b590b5ac3b3f72b902292d18e1475db7fb6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 28 Feb 2024 12:57:46 +0900 Subject: [PATCH 139/147] Update regex patterns with rbinstall.rb --- test/ruby/test_default_gems.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb index 71371b46c3b784..b9de33cc78d5b8 100644 --- a/test/ruby/test_default_gems.rb +++ b/test/ruby/test_default_gems.rb @@ -5,10 +5,11 @@ class TestDefaultGems < Test::Unit::TestCase def self.load(file) code = File.read(file, mode: "r:UTF-8:-", &:read) + # These regex patterns are from load_gemspec method of rbinstall.rb. # - `git ls-files` is useless under ruby's repository # - `2>/dev/null` works only on Unix-like platforms - code.gsub!(/`git.*?`/, '""') - code.gsub!(/\[git.*?\]/, '[echo]') + code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m, '[]') + code.gsub!(/IO\.popen\(.*git.*?\)/, '[].each') eval(code, binding, file) end From 8316cb213c2a32fbb7cb7314e2595730568181ad Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 28 Feb 2024 16:08:56 +0900 Subject: [PATCH 140/147] Fix to use `assert_crash_report` results --- test/ruby/test_rubyoptions.rb | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 2dd6ca3af82fce..03902e79f4cdf3 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -917,28 +917,24 @@ def assert_crash_report(path, cmd = nil) end def test_crash_report - assert_crash_report("%e.%f.%p.log") do |status, report| - assert_equal("#{File.basename(EnvUtil.rubybin)}.-e.#{status.pid}.log", report) - end + status, report = assert_crash_report("%e.%f.%p.log") + assert_equal("#{File.basename(EnvUtil.rubybin)}.-e.#{status.pid}.log", report) end def test_crash_report_script - assert_crash_report("%e.%f.%p.log", "bug.rb") do |status, report| - assert_equal("#{File.basename(EnvUtil.rubybin)}.bug.rb.#{status.pid}.log", report) - end + status, report = assert_crash_report("%e.%f.%p.log", "bug.rb") + assert_equal("#{File.basename(EnvUtil.rubybin)}.bug.rb.#{status.pid}.log", report) end def test_crash_report_executable_path omit if EnvUtil.rubybin.size > 245 - assert_crash_report("%E.%p.log") do |status, report| - assert_equal("#{EnvUtil.rubybin.tr('/', '!')}.#{status.pid}.log", report) - end + status, report = assert_crash_report("%E.%p.log") + assert_equal("#{EnvUtil.rubybin.tr('/', '!')}.#{status.pid}.log", report) end def test_crash_report_script_path - assert_crash_report("%F.%p.log", "test/bug.rb") do |status, report| - assert_equal("test!bug.rb.#{status.pid}.log", report) - end + status, report = assert_crash_report("%F.%p.log", "test/bug.rb") + assert_equal("test!bug.rb.#{status.pid}.log", report) end def test_crash_report_pipe From eb6eb1d4e8572fffd7bce6789eb8e87669293eef Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 28 Feb 2024 17:53:02 +0900 Subject: [PATCH 141/147] Fix crash report path test on Windows --- test/ruby/test_rubyoptions.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 03902e79f4cdf3..5eede5c4bae06a 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -929,7 +929,8 @@ def test_crash_report_script def test_crash_report_executable_path omit if EnvUtil.rubybin.size > 245 status, report = assert_crash_report("%E.%p.log") - assert_equal("#{EnvUtil.rubybin.tr('/', '!')}.#{status.pid}.log", report) + path = EnvUtil.rubybin.sub(/\A\w\K:[\/\\]/, '!').tr_s('/', '!') + assert_equal("#{path}.#{status.pid}.log", report) end def test_crash_report_script_path From 8b556d39d279c871469f6de665191dfbd502d564 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 28 Feb 2024 09:32:59 -0500 Subject: [PATCH 142/147] [ruby/prism] Refactor static literals into hash https://github.com/ruby/prism/commit/62382d3967 --- prism/static_literals.c | 182 +++++++++++++++++++++++++++++++--------- prism/static_literals.h | 44 ++++------ 2 files changed, 159 insertions(+), 67 deletions(-) diff --git a/prism/static_literals.c b/prism/static_literals.c index 5fba5d790effc5..74bdf6ead022c0 100644 --- a/prism/static_literals.c +++ b/prism/static_literals.c @@ -1,40 +1,141 @@ #include "prism/static_literals.h" -/** - * Insert a node into the given sorted list. This will return false if the node - * was not already in the list, and true if it was. - */ -static pm_node_t * -pm_node_list_insert(const pm_parser_t *parser, pm_node_list_t *list, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { - size_t low = 0; - size_t high = list->size; - - while (low < high) { - size_t mid = (low + high) / 2; - int result = compare(parser, list->nodes[mid], node); - - // If we find a match, then replace the old node with the new one and - // return the old one. - if (result == 0) { - pm_node_t *result = list->nodes[mid]; - list->nodes[mid] = node; - return result; +static inline uint32_t +murmur_scramble(uint32_t value) { + value *= 0xcc9e2d51; + value = (value << 15) | (value >> 17); + value *= 0x1b873593; + return value; +} + +static uint32_t +murmur_hash(const uint8_t *key, size_t length) { + uint32_t h = 0x9747b28c; + uint32_t k; + + /* Read in groups of 4. */ + for (size_t i = length >> 2; i; i--) { + // Here is a source of differing results across endiannesses. + // A swap here has no effects on hash properties though. + memcpy(&k, key, sizeof(uint32_t)); + key += sizeof(uint32_t); + h ^= murmur_scramble(k); + h = (h << 13) | (h >> 19); + h = h * 5 + 0xe6546b64; + } + + /* Read the rest. */ + k = 0; + for (size_t i = length & 3; i; i--) { + k <<= 8; + k |= key[i - 1]; + } + + // A swap is *not* necessary here because the preceding loop already + // places the low bytes in the low places according to whatever endianness + // we use. Swaps only apply when the memory is copied in a chunk. + h ^= murmur_scramble(k); + + /* Finalize. */ + h ^= length; + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +static uint32_t +node_hash(const pm_parser_t *parser, const pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_INTEGER_NODE: { + const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value; + const uint32_t *value = &integer->head.value; + + uint32_t hash = murmur_hash((const uint8_t *) value, sizeof(uint32_t)); + for (const pm_integer_word_t *word = integer->head.next; word != NULL; word = word->next) { + value = &word->value; + hash ^= murmur_hash((const uint8_t *) value, sizeof(uint32_t)); + } + + return hash; + } + case PM_SOURCE_LINE_NODE: { + const pm_line_column_t line_column = pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line); + const int32_t *value = &line_column.line; + return murmur_hash((const uint8_t *) value, sizeof(int32_t)); } + case PM_FLOAT_NODE: { + const double *value = &((const pm_float_node_t *) node)->value; + return murmur_hash((const uint8_t *) value, sizeof(double)); + } + case PM_RATIONAL_NODE: { + const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric; + return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type); + } + case PM_IMAGINARY_NODE: { + const pm_node_t *numeric = ((const pm_imaginary_node_t *) node)->numeric; + return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type); + } + case PM_STRING_NODE: { + const pm_string_t *value = &((const pm_string_node_t *) node)->unescaped; + return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); + } + case PM_SOURCE_FILE_NODE: { + const pm_string_t *value = &((const pm_source_file_node_t *) node)->filepath; + return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); + } + case PM_REGULAR_EXPRESSION_NODE: { + const pm_string_t *value = &((const pm_regular_expression_node_t *) node)->unescaped; + return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); + } + case PM_SYMBOL_NODE: { + const pm_string_t *value = &((const pm_symbol_node_t *) node)->unescaped; + return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); + } + default: + assert(false && "unreachable"); + return 0; + } +} + +static pm_node_t * +pm_node_hash_insert(const pm_parser_t *parser, pm_node_hash_t *hash, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { + if (hash->size * 2 >= hash->capacity) { + size_t new_capacity = hash->capacity == 0 ? 4 : hash->capacity * 2; + pm_node_t **new_nodes = calloc(new_capacity, sizeof(pm_node_t *)); + if (new_nodes == NULL) return NULL; + + for (size_t i = 0; i < hash->capacity; i++) { + pm_node_t *node = hash->nodes[i]; - if (result < 0) { - low = mid + 1; - } else { - high = mid; + if (node != NULL) { + size_t index = node_hash(parser, node) % new_capacity; + new_nodes[index] = node; + } } + + hash->nodes = new_nodes; + hash->capacity = new_capacity; + } + + size_t index = node_hash(parser, node) % hash->capacity; + while (hash->nodes[index] != NULL) { + if (compare(parser, hash->nodes[index], node) == 0) break; + index = (index + 1) % hash->capacity; } - pm_node_list_grow(list); - memmove(&list->nodes[low + 1], &list->nodes[low], (list->size - low) * sizeof(pm_node_t *)); + pm_node_t *result = hash->nodes[index]; + if (result == NULL) hash->size++; - list->nodes[low] = node; - list->size++; + hash->nodes[index] = node; + return result; +} - return NULL; +static void +pm_node_hash_free(pm_node_hash_t *hash) { + if (hash->capacity > 0) free(hash->nodes); } /** @@ -168,19 +269,19 @@ pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: case PM_SOURCE_LINE_NODE: - return pm_node_list_insert(parser, &literals->integer_nodes, node, pm_compare_integer_nodes); + return pm_node_hash_insert(parser, &literals->integer_nodes, node, pm_compare_integer_nodes); case PM_FLOAT_NODE: - return pm_node_list_insert(parser, &literals->float_nodes, node, pm_compare_float_nodes); + return pm_node_hash_insert(parser, &literals->float_nodes, node, pm_compare_float_nodes); case PM_RATIONAL_NODE: case PM_IMAGINARY_NODE: - return pm_node_list_insert(parser, &literals->rational_nodes, node, pm_compare_number_nodes); + return pm_node_hash_insert(parser, &literals->number_nodes, node, pm_compare_number_nodes); case PM_STRING_NODE: case PM_SOURCE_FILE_NODE: - return pm_node_list_insert(parser, &literals->string_nodes, node, pm_compare_string_nodes); + return pm_node_hash_insert(parser, &literals->string_nodes, node, pm_compare_string_nodes); case PM_REGULAR_EXPRESSION_NODE: - return pm_node_list_insert(parser, &literals->regexp_nodes, node, pm_compare_regular_expression_nodes); + return pm_node_hash_insert(parser, &literals->regexp_nodes, node, pm_compare_regular_expression_nodes); case PM_SYMBOL_NODE: - return pm_node_list_insert(parser, &literals->symbol_nodes, node, pm_compare_string_nodes); + return pm_node_hash_insert(parser, &literals->symbol_nodes, node, pm_compare_string_nodes); case PM_TRUE_NODE: { pm_node_t *duplicated = literals->true_node; literals->true_node = node; @@ -211,11 +312,10 @@ pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals */ void pm_static_literals_free(pm_static_literals_t *literals) { - pm_node_list_free(&literals->integer_nodes); - pm_node_list_free(&literals->float_nodes); - pm_node_list_free(&literals->rational_nodes); - pm_node_list_free(&literals->imaginary_nodes); - pm_node_list_free(&literals->string_nodes); - pm_node_list_free(&literals->regexp_nodes); - pm_node_list_free(&literals->symbol_nodes); + pm_node_hash_free(&literals->integer_nodes); + pm_node_hash_free(&literals->float_nodes); + pm_node_hash_free(&literals->number_nodes); + pm_node_hash_free(&literals->string_nodes); + pm_node_hash_free(&literals->regexp_nodes); + pm_node_hash_free(&literals->symbol_nodes); } diff --git a/prism/static_literals.h b/prism/static_literals.h index 837d355985c6a6..89ebc52d5c4b99 100644 --- a/prism/static_literals.h +++ b/prism/static_literals.h @@ -14,6 +14,12 @@ #include #include +typedef struct { + pm_node_t **nodes; + size_t size; + size_t capacity; +} pm_node_hash_t; + /** * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes * to alert the user of potential issues. To do this, we keep a set of the nodes @@ -24,48 +30,34 @@ */ typedef struct { /** - * This is the set of IntegerNode and SourceLineNode instances. We store - * them in a sorted list so that we can binary search through them to find - * duplicates. - */ - pm_node_list_t integer_nodes; - - /** - * This is the set of FloatNode instances. We store them in a sorted list so - * that we can binary search through them to find duplicates. + * This is the set of IntegerNode and SourceLineNode instances. */ - pm_node_list_t float_nodes; + pm_node_hash_t integer_nodes; /** - * This is the set of RationalNode instances. We store them in a flat list - * that must be searched linearly. + * This is the set of FloatNode instances. */ - pm_node_list_t rational_nodes; + pm_node_hash_t float_nodes; /** - * This is the set of ImaginaryNode instances. We store them in a flat list - * that must be searched linearly. + * This is the set of RationalNode and ImaginaryNode instances. */ - pm_node_list_t imaginary_nodes; + pm_node_hash_t number_nodes; /** - * This is the set of StringNode and SourceFileNode instances. We store them - * in a sorted list so that we can binary search through them to find - * duplicates. + * This is the set of StringNode and SourceFileNode instances. */ - pm_node_list_t string_nodes; + pm_node_hash_t string_nodes; /** - * This is the set of RegularExpressionNode instances. We store them in a - * sorted list so that we can binary search through them to find duplicates. + * This is the set of RegularExpressionNode instances. */ - pm_node_list_t regexp_nodes; + pm_node_hash_t regexp_nodes; /** - * This is the set of SymbolNode instances. We store them in a sorted list - * so that we can binary search through them to find duplicates. + * This is the set of SymbolNode instances. */ - pm_node_list_t symbol_nodes; + pm_node_hash_t symbol_nodes; /** * A pointer to the last TrueNode instance that was inserted, or NULL. From c990cc706c959e280ad9ea10d47672ad6227a810 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 28 Feb 2024 09:58:53 -0500 Subject: [PATCH 143/147] [ruby/prism] Switch static literals to use a hash https://github.com/ruby/prism/commit/82e6f36e8f --- prism/static_literals.c | 133 +++++++++++++++++++++++++++------------- prism/static_literals.h | 12 +++- 2 files changed, 101 insertions(+), 44 deletions(-) diff --git a/prism/static_literals.c b/prism/static_literals.c index 74bdf6ead022c0..17be22c2e78121 100644 --- a/prism/static_literals.c +++ b/prism/static_literals.c @@ -8,48 +8,50 @@ murmur_scramble(uint32_t value) { return value; } +/** + * Murmur hash (https://en.wikipedia.org/wiki/MurmurHash) is a non-cryptographic + * general-purpose hash function. It is fast, which is what we care about in + * this case. + */ static uint32_t murmur_hash(const uint8_t *key, size_t length) { - uint32_t h = 0x9747b28c; - uint32_t k; - - /* Read in groups of 4. */ - for (size_t i = length >> 2; i; i--) { - // Here is a source of differing results across endiannesses. - // A swap here has no effects on hash properties though. - memcpy(&k, key, sizeof(uint32_t)); + uint32_t hash = 0x9747b28c; + uint32_t segment; + + for (size_t index = length >> 2; index; index--) { + memcpy(&segment, key, sizeof(uint32_t)); key += sizeof(uint32_t); - h ^= murmur_scramble(k); - h = (h << 13) | (h >> 19); - h = h * 5 + 0xe6546b64; + hash ^= murmur_scramble(segment); + hash = (hash << 13) | (hash >> 19); + hash = hash * 5 + 0xe6546b64; } - /* Read the rest. */ - k = 0; - for (size_t i = length & 3; i; i--) { - k <<= 8; - k |= key[i - 1]; + segment = 0; + for (size_t index = length & 3; index; index--) { + segment <<= 8; + segment |= key[index - 1]; } - // A swap is *not* necessary here because the preceding loop already - // places the low bytes in the low places according to whatever endianness - // we use. Swaps only apply when the memory is copied in a chunk. - h ^= murmur_scramble(k); - - /* Finalize. */ - h ^= length; - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - return h; + hash ^= murmur_scramble(segment); + hash ^= (uint32_t) length; + hash ^= hash >> 16; + hash *= 0x85ebca6b; + hash ^= hash >> 13; + hash *= 0xc2b2ae35; + hash ^= hash >> 16; + return hash; } +/** + * Return the hash of the given node. It is important that nodes that have + * equivalent static literal values have the same hash. This is because we use + * these hashes to look for duplicates. + */ static uint32_t node_hash(const pm_parser_t *parser, const pm_node_t *node) { switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: { + // Integers hash their value. const pm_integer_t *integer = &((const pm_integer_node_t *) node)->value; const uint32_t *value = &integer->head.value; @@ -62,35 +64,51 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) { return hash; } case PM_SOURCE_LINE_NODE: { + // Source lines hash their line number. const pm_line_column_t line_column = pm_newline_list_line_column(&parser->newline_list, node->location.start, parser->start_line); const int32_t *value = &line_column.line; return murmur_hash((const uint8_t *) value, sizeof(int32_t)); } case PM_FLOAT_NODE: { + // Floats hash their value. const double *value = &((const pm_float_node_t *) node)->value; return murmur_hash((const uint8_t *) value, sizeof(double)); } case PM_RATIONAL_NODE: { + // Rationals hash their numeric value. Because their numeric value + // is stored as a subnode, we hash that node and then mix in the + // fact that this is a rational node. const pm_node_t *numeric = ((const pm_rational_node_t *) node)->numeric; return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type); } case PM_IMAGINARY_NODE: { + // Imaginaries hash their numeric value. Because their numeric value + // is stored as a subnode, we hash that node and then mix in the + // fact that this is an imaginary node. const pm_node_t *numeric = ((const pm_imaginary_node_t *) node)->numeric; return node_hash(parser, numeric) ^ murmur_scramble((uint32_t) node->type); } case PM_STRING_NODE: { + // Strings hash their value and mix in their flags so that different + // encodings are not considered equal. const pm_string_t *value = &((const pm_string_node_t *) node)->unescaped; return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); } case PM_SOURCE_FILE_NODE: { + // Source files hash their value and mix in their flags so that + // different encodings are not considered equal. const pm_string_t *value = &((const pm_source_file_node_t *) node)->filepath; return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); } case PM_REGULAR_EXPRESSION_NODE: { + // Regular expressions hash their value and mix in their flags so + // that different encodings are not considered equal. const pm_string_t *value = &((const pm_regular_expression_node_t *) node)->unescaped; return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); } case PM_SYMBOL_NODE: { + // Symbols hash their value and mix in their flags so that different + // encodings are not considered equal. const pm_string_t *value = &((const pm_symbol_node_t *) node)->unescaped; return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node->flags); } @@ -100,32 +118,60 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) { } } +/** + * Insert a node into the node hash. It accepts the hash that should hold the + * new node, the parser that generated the node, the node to insert, and a + * comparison function. The comparison function is used for collision detection, + * and must be able to compare all node types that will be stored in this hash. + */ static pm_node_t * -pm_node_hash_insert(const pm_parser_t *parser, pm_node_hash_t *hash, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { +pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *node, int (*compare)(const pm_parser_t *parser, const pm_node_t *left, const pm_node_t *right)) { + // If we are out of space, we need to resize the hash. This will cause all + // of the nodes to be rehashed and reinserted into the new hash. if (hash->size * 2 >= hash->capacity) { - size_t new_capacity = hash->capacity == 0 ? 4 : hash->capacity * 2; + // First, allocate space for the new node list. + uint32_t new_capacity = hash->capacity == 0 ? 4 : hash->capacity * 2; pm_node_t **new_nodes = calloc(new_capacity, sizeof(pm_node_t *)); if (new_nodes == NULL) return NULL; - for (size_t i = 0; i < hash->capacity; i++) { - pm_node_t *node = hash->nodes[i]; + // It turns out to be more efficient to mask the hash value than to use + // the modulo operator. Because our capacities are always powers of two, + // we can use a bitwise AND to get the same result as the modulo + // operator. + uint32_t mask = new_capacity - 1; + + // Now, rehash all of the nodes into the new list. + for (uint32_t index = 0; index < hash->capacity; index++) { + pm_node_t *node = hash->nodes[index]; if (node != NULL) { - size_t index = node_hash(parser, node) % new_capacity; + uint32_t index = node_hash(parser, node) & mask; new_nodes[index] = node; } } + // Finally, free the old node list and update the hash. + free(hash->nodes); hash->nodes = new_nodes; hash->capacity = new_capacity; } - size_t index = node_hash(parser, node) % hash->capacity; + // Now, insert the node into the hash. + uint32_t mask = hash->capacity - 1; + uint32_t index = node_hash(parser, node) & mask; + + // We use linear probing to resolve collisions. This means that if the + // current index is occupied, we will move to the next index and try again. + // We are guaranteed that this will eventually find an empty slot because we + // resize the hash when it gets too full. while (hash->nodes[index] != NULL) { if (compare(parser, hash->nodes[index], node) == 0) break; - index = (index + 1) % hash->capacity; + index = (index + 1) & mask; } + // If the current index is occupied, we need to return the node that was + // already in the hash. Otherwise, we can just increment the size and insert + // the new node. pm_node_t *result = hash->nodes[index]; if (result == NULL) hash->size++; @@ -133,6 +179,9 @@ pm_node_hash_insert(const pm_parser_t *parser, pm_node_hash_t *hash, pm_node_t * return result; } +/** + * Free the internal memory associated with the given node hash. + */ static void pm_node_hash_free(pm_node_hash_t *hash) { if (hash->capacity > 0) free(hash->nodes); @@ -269,19 +318,19 @@ pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals switch (PM_NODE_TYPE(node)) { case PM_INTEGER_NODE: case PM_SOURCE_LINE_NODE: - return pm_node_hash_insert(parser, &literals->integer_nodes, node, pm_compare_integer_nodes); + return pm_node_hash_insert(&literals->integer_nodes, parser, node, pm_compare_integer_nodes); case PM_FLOAT_NODE: - return pm_node_hash_insert(parser, &literals->float_nodes, node, pm_compare_float_nodes); + return pm_node_hash_insert(&literals->float_nodes, parser, node, pm_compare_float_nodes); case PM_RATIONAL_NODE: case PM_IMAGINARY_NODE: - return pm_node_hash_insert(parser, &literals->number_nodes, node, pm_compare_number_nodes); + return pm_node_hash_insert(&literals->number_nodes, parser, node, pm_compare_number_nodes); case PM_STRING_NODE: case PM_SOURCE_FILE_NODE: - return pm_node_hash_insert(parser, &literals->string_nodes, node, pm_compare_string_nodes); + return pm_node_hash_insert(&literals->string_nodes, parser, node, pm_compare_string_nodes); case PM_REGULAR_EXPRESSION_NODE: - return pm_node_hash_insert(parser, &literals->regexp_nodes, node, pm_compare_regular_expression_nodes); + return pm_node_hash_insert(&literals->regexp_nodes, parser, node, pm_compare_regular_expression_nodes); case PM_SYMBOL_NODE: - return pm_node_hash_insert(parser, &literals->symbol_nodes, node, pm_compare_string_nodes); + return pm_node_hash_insert(&literals->symbol_nodes, parser, node, pm_compare_string_nodes); case PM_TRUE_NODE: { pm_node_t *duplicated = literals->true_node; literals->true_node = node; diff --git a/prism/static_literals.h b/prism/static_literals.h index 89ebc52d5c4b99..2a3d815fa9ef86 100644 --- a/prism/static_literals.h +++ b/prism/static_literals.h @@ -14,10 +14,18 @@ #include #include +/** + * An internal hash table for a set of nodes. + */ typedef struct { + /** The array of nodes in the hash table. */ pm_node_t **nodes; - size_t size; - size_t capacity; + + /** The size of the hash table. */ + uint32_t size; + + /** The space that has been allocated in the hash table. */ + uint32_t capacity; } pm_node_hash_t; /** From 48f433fd408f5f493aa0ac4638ee9ab773b8d10c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:50:08 -0500 Subject: [PATCH 144/147] Change T_ZOMBIE flag check from an assertion Assertions are only enable on debug builds, so it will now check for flags of T_ZOMBIE objects on all builds in GC.verify_internal_consistency. --- gc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gc.c b/gc.c index df61246d4616b9..06a99f6641d246 100644 --- a/gc.c +++ b/gc.c @@ -7554,8 +7554,13 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, } else { if (BUILTIN_TYPE(obj) == T_ZOMBIE) { - GC_ASSERT((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) == T_ZOMBIE); data->zombie_object_count++; + + if ((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) != T_ZOMBIE) { + fprintf(stderr, "verify_internal_consistency_i: T_ZOMBIE has extra flags set: %s\n", + obj_info(obj)); + data->err_count++; + } } } if (poisoned) { From 7b69563b365317fb9c70e4bed996b5871ef7889a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 Feb 2024 11:50:21 -0500 Subject: [PATCH 145/147] Add check for finalizer in verify_internal_constency This adds a check in GC.verify_internal_constency that FL_FINALIZE flags is set if, and only if it is in finalizer_table. --- gc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gc.c b/gc.c index 06a99f6641d246..d488286ff9301a 100644 --- a/gc.c +++ b/gc.c @@ -7561,6 +7561,13 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, obj_info(obj)); data->err_count++; } + + if (!!FL_TEST(obj, FL_FINALIZE) != !!st_is_member(finalizer_table, obj)) { + fprintf(stderr, "verify_internal_consistency_i: FL_FINALIZE %s but %s finalizer_table: %s\n", + FL_TEST(obj, FL_FINALIZE) ? "set" : "not set", st_is_member(finalizer_table, obj) ? "in" : "not in", + obj_info(obj)); + data->err_count++; + } } } if (poisoned) { From 742abbf7705d69314373c6255784af02bbe72882 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 27 Feb 2024 08:31:47 -0500 Subject: [PATCH 146/147] Switch {prism: true} to {parser: :prism} in ISeq.to_a --- iseq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iseq.c b/iseq.c index 36fbe9d2f421aa..a63516c02b64d0 100644 --- a/iseq.c +++ b/iseq.c @@ -3380,7 +3380,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) #ifdef USE_ISEQ_NODE_ID rb_hash_aset(misc, ID2SYM(rb_intern("node_ids")), node_ids); #endif - rb_hash_aset(misc, ID2SYM(rb_intern("prism")), iseq_body->prism ? Qtrue : Qfalse); + rb_hash_aset(misc, ID2SYM(rb_intern("parser")), iseq_body->prism ? ID2SYM(rb_intern("prism")) : ID2SYM(rb_intern("parse.y"))); /* * [:magic, :major_version, :minor_version, :format_type, :misc, From 1cef366319ed6f30276de5534f226cac4bd9047e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 28 Feb 2024 10:38:48 -0500 Subject: [PATCH 147/147] [PRISM] Factor in CLI options for prism --- ruby.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ruby.c b/ruby.c index 335935a5d8fe9f..fde179ef7ced19 100644 --- a/ruby.c +++ b/ruby.c @@ -2084,6 +2084,7 @@ static void prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) { ruby_opt_init(opt); + memset(result, 0, sizeof(pm_parse_result_t)); if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) { rb_category_warn( @@ -2095,11 +2096,14 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) ); } - memset(result, 0, sizeof(*result)); - result->options.line = 1; + pm_options_t *options = &result->options; + pm_options_line_set(options, 1); + pm_options_command_line_p_set(options, opt->do_print); + pm_options_command_line_n_set(options, opt->do_loop); + pm_options_command_line_l_set(options, opt->do_line); + pm_options_command_line_a_set(options, opt->do_split); VALUE error; - if (strcmp(opt->script, "-") == 0) { rb_raise(rb_eRuntimeError, "Prism support for streaming code from stdin is not currently supported"); }