syntax_tree 5.1.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +4 -0
- data/.github/workflows/auto-merge.yml +1 -1
- data/.github/workflows/main.yml +5 -2
- data/.gitmodules +6 -0
- data/.rubocop.yml +7 -1
- data/CHANGELOG.md +12 -1
- data/Gemfile.lock +7 -7
- data/Rakefile +7 -0
- data/exe/yarv +63 -0
- data/lib/syntax_tree/node.rb +19 -10
- data/lib/syntax_tree/parser.rb +1 -1
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/yarv/assembler.rb +7 -7
- data/lib/syntax_tree/yarv/bf.rb +13 -16
- data/lib/syntax_tree/yarv/compiler.rb +24 -13
- data/lib/syntax_tree/yarv/decompiler.rb +9 -0
- data/lib/syntax_tree/yarv/disassembler.rb +3 -2
- data/lib/syntax_tree/yarv/instruction_sequence.rb +190 -86
- data/lib/syntax_tree/yarv/instructions.rb +211 -42
- data/lib/syntax_tree/yarv/legacy.rb +26 -3
- data/lib/syntax_tree/yarv/vm.rb +624 -0
- data/lib/syntax_tree/yarv.rb +0 -269
- data/lib/syntax_tree.rb +1 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c5651bab4283bf0f1c451619e5c3b54c9b229d1fb5050a3732918bccb7be177
|
4
|
+
data.tar.gz: 2cda5e4b62a3beac16dddc8ff9298624c161bc99c3b82ba2ecc10d8d643aac4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81d331f10356569b23ada917cea2ecf5a2dd1073bc927e39ba0b6036ea4b79813ce7b1e4826f39d919559cdbb5925da8a5680d72653d64d0eb05979729356173
|
7
|
+
data.tar.gz: 53b320f073ef5e15efcd2e7d706e959e3ade48f18ab0f131a588a183276aeea3352cf6da0ef2ad842dc0c9bf517ac4c441ee4fbe98fa73dd156e845d5d4007d7
|
data/.github/dependabot.yml
CHANGED
data/.github/workflows/main.yml
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
name: Main
|
2
|
+
|
2
3
|
on:
|
3
4
|
- push
|
4
5
|
- pull_request
|
6
|
+
|
5
7
|
jobs:
|
6
8
|
ci:
|
7
9
|
strategy:
|
@@ -11,13 +13,14 @@ jobs:
|
|
11
13
|
- '2.7.0'
|
12
14
|
- '3.0'
|
13
15
|
- '3.1'
|
16
|
+
- '3.2'
|
14
17
|
- head
|
15
18
|
- truffleruby-head
|
16
19
|
name: CI
|
17
20
|
runs-on: ubuntu-latest
|
18
21
|
env:
|
19
22
|
CI: true
|
20
|
-
TESTOPTS: --verbose
|
23
|
+
# TESTOPTS: --verbose
|
21
24
|
steps:
|
22
25
|
- uses: actions/checkout@master
|
23
26
|
- uses: ruby/setup-ruby@v1
|
@@ -37,7 +40,7 @@ jobs:
|
|
37
40
|
- uses: ruby/setup-ruby@v1
|
38
41
|
with:
|
39
42
|
bundler-cache: true
|
40
|
-
ruby-version: '3.
|
43
|
+
ruby-version: '3.2'
|
41
44
|
- name: Check
|
42
45
|
run: |
|
43
46
|
bundle exec rake stree:check
|
data/.gitmodules
ADDED
data/.rubocop.yml
CHANGED
@@ -7,7 +7,7 @@ AllCops:
|
|
7
7
|
SuggestExtensions: false
|
8
8
|
TargetRubyVersion: 2.7
|
9
9
|
Exclude:
|
10
|
-
- '{.git,.github,bin,coverage,pkg,test/fixtures,vendor,tmp}/**/*'
|
10
|
+
- '{.git,.github,bin,coverage,pkg,spec,test/fixtures,vendor,tmp}/**/*'
|
11
11
|
- test.rb
|
12
12
|
|
13
13
|
Layout/LineLength:
|
@@ -43,6 +43,9 @@ Lint/NonLocalExitFromIterator:
|
|
43
43
|
Lint/RedundantRequireStatement:
|
44
44
|
Enabled: false
|
45
45
|
|
46
|
+
Lint/RescueException:
|
47
|
+
Enabled: false
|
48
|
+
|
46
49
|
Lint/SuppressedException:
|
47
50
|
Enabled: false
|
48
51
|
|
@@ -144,3 +147,6 @@ Style/SpecialGlobalVars:
|
|
144
147
|
|
145
148
|
Style/StructInheritance:
|
146
149
|
Enabled: false
|
150
|
+
|
151
|
+
Style/YodaExpression:
|
152
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [5.2.0] - 2023-01-04
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- An experiment in evaluating compiled instruction sequences has been added to Syntax Tree. This is subject to change, so it will not be well documented or testing at the moment. It does not impact other functionality.
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
|
17
|
+
- Empty parentheses on method calls will now be left in place. Previously they were left in place if the method being called looked like a constant. Now they are left in place for all method calls since the method name can mirror the name of a local variable, in which case the parentheses are required.
|
18
|
+
|
9
19
|
## [5.1.0] - 2022-12-28
|
10
20
|
|
11
21
|
### Added
|
@@ -471,7 +481,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
471
481
|
|
472
482
|
- 🎉 Initial release! 🎉
|
473
483
|
|
474
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v5.
|
484
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v5.2.0...HEAD
|
485
|
+
[5.2.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v5.1.0...v5.2.0
|
475
486
|
[5.1.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v5.0.1...v5.1.0
|
476
487
|
[5.0.1]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v5.0.0...v5.0.1
|
477
488
|
[5.0.0]: https://github.com/ruby-syntax-tree/syntax_tree/compare/v4.3.0...v5.0.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
syntax_tree (5.
|
4
|
+
syntax_tree (5.2.0)
|
5
5
|
prettier_print (>= 1.2.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -10,26 +10,26 @@ GEM
|
|
10
10
|
ast (2.4.2)
|
11
11
|
docile (1.4.0)
|
12
12
|
json (2.6.3)
|
13
|
-
minitest (5.
|
13
|
+
minitest (5.17.0)
|
14
14
|
parallel (1.22.1)
|
15
|
-
parser (3.
|
15
|
+
parser (3.2.0.0)
|
16
16
|
ast (~> 2.4.1)
|
17
17
|
prettier_print (1.2.0)
|
18
18
|
rainbow (3.1.1)
|
19
19
|
rake (13.0.6)
|
20
20
|
regexp_parser (2.6.1)
|
21
21
|
rexml (3.2.5)
|
22
|
-
rubocop (1.
|
22
|
+
rubocop (1.42.0)
|
23
23
|
json (~> 2.3)
|
24
24
|
parallel (~> 1.10)
|
25
25
|
parser (>= 3.1.2.1)
|
26
26
|
rainbow (>= 2.2.2, < 4.0)
|
27
27
|
regexp_parser (>= 1.8, < 3.0)
|
28
28
|
rexml (>= 3.2.5, < 4.0)
|
29
|
-
rubocop-ast (>= 1.
|
29
|
+
rubocop-ast (>= 1.24.1, < 2.0)
|
30
30
|
ruby-progressbar (~> 1.7)
|
31
31
|
unicode-display_width (>= 1.4.0, < 3.0)
|
32
|
-
rubocop-ast (1.24.
|
32
|
+
rubocop-ast (1.24.1)
|
33
33
|
parser (>= 3.1.1.0)
|
34
34
|
ruby-progressbar (1.11.0)
|
35
35
|
simplecov (0.22.0)
|
@@ -38,7 +38,7 @@ GEM
|
|
38
38
|
simplecov_json_formatter (~> 0.1)
|
39
39
|
simplecov-html (0.12.3)
|
40
40
|
simplecov_json_formatter (0.1.4)
|
41
|
-
unicode-display_width (2.
|
41
|
+
unicode-display_width (2.4.1)
|
42
42
|
|
43
43
|
PLATFORMS
|
44
44
|
arm64-darwin-21
|
data/Rakefile
CHANGED
@@ -26,3 +26,10 @@ end
|
|
26
26
|
|
27
27
|
SyntaxTree::Rake::CheckTask.new(&configure)
|
28
28
|
SyntaxTree::Rake::WriteTask.new(&configure)
|
29
|
+
|
30
|
+
desc "Run mspec tests using YARV emulation"
|
31
|
+
task :spec do
|
32
|
+
Dir["./spec/ruby/language/**/*_spec.rb"].each do |filepath|
|
33
|
+
sh "exe/yarv ./spec/mspec/bin/mspec-tag #{filepath}"
|
34
|
+
end
|
35
|
+
end
|
data/exe/yarv
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
$:.unshift(File.expand_path("../lib", __dir__))
|
5
|
+
|
6
|
+
require "syntax_tree"
|
7
|
+
|
8
|
+
# Require these here so that we can run binding.irb without having them require
|
9
|
+
# anything that we've already patched.
|
10
|
+
require "irb"
|
11
|
+
require "irb/completion"
|
12
|
+
require "irb/color_printer"
|
13
|
+
require "readline"
|
14
|
+
|
15
|
+
# First, create an instance of our virtual machine.
|
16
|
+
events =
|
17
|
+
if ENV["DEBUG"]
|
18
|
+
SyntaxTree::YARV::VM::STDOUTEvents.new
|
19
|
+
else
|
20
|
+
SyntaxTree::YARV::VM::NullEvents.new
|
21
|
+
end
|
22
|
+
|
23
|
+
vm = SyntaxTree::YARV::VM.new(events)
|
24
|
+
|
25
|
+
# Next, set up a bunch of aliases for methods that we're going to hook into in
|
26
|
+
# order to set up our virtual machine.
|
27
|
+
class << Kernel
|
28
|
+
alias yarv_require require
|
29
|
+
alias yarv_require_relative require_relative
|
30
|
+
alias yarv_load load
|
31
|
+
alias yarv_eval eval
|
32
|
+
alias yarv_throw throw
|
33
|
+
alias yarv_catch catch
|
34
|
+
end
|
35
|
+
|
36
|
+
# Next, patch the methods that we just aliased so that they use our virtual
|
37
|
+
# machine's versions instead. This allows us to load Ruby files and have them
|
38
|
+
# execute in our virtual machine instead of the runtime environment.
|
39
|
+
[Kernel, Kernel.singleton_class].each do |klass|
|
40
|
+
klass.define_method(:require) { |filepath| vm.require(filepath) }
|
41
|
+
|
42
|
+
klass.define_method(:load) { |filepath| vm.load(filepath) }
|
43
|
+
|
44
|
+
# klass.define_method(:require_relative) do |filepath|
|
45
|
+
# vm.require_relative(filepath)
|
46
|
+
# end
|
47
|
+
|
48
|
+
# klass.define_method(:eval) do |
|
49
|
+
# source,
|
50
|
+
# binding = TOPLEVEL_BINDING,
|
51
|
+
# filename = "(eval)",
|
52
|
+
# lineno = 1
|
53
|
+
# |
|
54
|
+
# vm.eval(source, binding, filename, lineno)
|
55
|
+
# end
|
56
|
+
|
57
|
+
# klass.define_method(:throw) { |tag, value = nil| vm.throw(tag, value) }
|
58
|
+
|
59
|
+
# klass.define_method(:catch) { |tag, &block| vm.catch(tag, &block) }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Finally, require the file that we want to execute.
|
63
|
+
vm.require_resolved(ARGV.shift)
|
data/lib/syntax_tree/node.rb
CHANGED
@@ -3001,16 +3001,25 @@ module SyntaxTree
|
|
3001
3001
|
else
|
3002
3002
|
q.format(message)
|
3003
3003
|
|
3004
|
-
|
3005
|
-
|
3006
|
-
|
3007
|
-
|
3008
|
-
|
3009
|
-
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
|
3004
|
+
# Note that this explicitly leaves parentheses in place even if they are
|
3005
|
+
# empty. There are two reasons we would need to do this. The first is if
|
3006
|
+
# we're calling something that looks like a constant, as in:
|
3007
|
+
#
|
3008
|
+
# Foo()
|
3009
|
+
#
|
3010
|
+
# In this case if we remove the parentheses then this becomes a constant
|
3011
|
+
# reference and not a method call. The second is if we're calling a
|
3012
|
+
# method that is the same name as a local variable that is in scope, as
|
3013
|
+
# in:
|
3014
|
+
#
|
3015
|
+
# foo = foo()
|
3016
|
+
#
|
3017
|
+
# In this case we have to keep the parentheses or else it treats this
|
3018
|
+
# like assigning nil to the local variable. Note that we could attempt
|
3019
|
+
# to be smarter about this by tracking the local variables that are in
|
3020
|
+
# scope, but for now it's simpler and more efficient to just leave the
|
3021
|
+
# parentheses in place.
|
3022
|
+
q.format(arguments) if arguments
|
3014
3023
|
end
|
3015
3024
|
end
|
3016
3025
|
|
data/lib/syntax_tree/parser.rb
CHANGED
data/lib/syntax_tree/version.rb
CHANGED
@@ -69,7 +69,7 @@ module SyntaxTree
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def assemble
|
72
|
-
iseq = InstructionSequence.new(
|
72
|
+
iseq = InstructionSequence.new("<main>", "<compiled>", 1, :top)
|
73
73
|
assemble_iseq(iseq, File.readlines(filepath, chomp: true))
|
74
74
|
|
75
75
|
iseq.compile!
|
@@ -138,7 +138,7 @@ module SyntaxTree
|
|
138
138
|
name = parse_symbol(name_value)
|
139
139
|
flags = parse_number(flags_value)
|
140
140
|
|
141
|
-
class_iseq = iseq.class_child_iseq(name.to_s,
|
141
|
+
class_iseq = iseq.class_child_iseq(name.to_s, 1)
|
142
142
|
assemble_iseq(class_iseq, body)
|
143
143
|
iseq.defineclass(name, class_iseq, flags)
|
144
144
|
when "defined"
|
@@ -153,7 +153,7 @@ module SyntaxTree
|
|
153
153
|
line_index += body.length
|
154
154
|
|
155
155
|
name = parse_symbol(operands)
|
156
|
-
method_iseq = iseq.method_child_iseq(name.to_s,
|
156
|
+
method_iseq = iseq.method_child_iseq(name.to_s, 1)
|
157
157
|
assemble_iseq(method_iseq, body)
|
158
158
|
|
159
159
|
iseq.definemethod(name, method_iseq)
|
@@ -162,7 +162,7 @@ module SyntaxTree
|
|
162
162
|
line_index += body.length
|
163
163
|
|
164
164
|
name = parse_symbol(operands)
|
165
|
-
method_iseq = iseq.method_child_iseq(name.to_s,
|
165
|
+
method_iseq = iseq.method_child_iseq(name.to_s, 1)
|
166
166
|
|
167
167
|
assemble_iseq(method_iseq, body)
|
168
168
|
iseq.definesmethod(name, method_iseq)
|
@@ -221,7 +221,7 @@ module SyntaxTree
|
|
221
221
|
body = parse_nested(lines[line_index..])
|
222
222
|
line_index += body.length
|
223
223
|
|
224
|
-
block_iseq = iseq.block_child_iseq(
|
224
|
+
block_iseq = iseq.block_child_iseq(1)
|
225
225
|
assemble_iseq(block_iseq, body)
|
226
226
|
block_iseq
|
227
227
|
end
|
@@ -249,7 +249,7 @@ module SyntaxTree
|
|
249
249
|
body = parse_nested(lines[line_index..])
|
250
250
|
line_index += body.length
|
251
251
|
|
252
|
-
block_iseq = iseq.block_child_iseq(
|
252
|
+
block_iseq = iseq.block_child_iseq(1)
|
253
253
|
assemble_iseq(block_iseq, body)
|
254
254
|
block_iseq
|
255
255
|
end
|
@@ -354,7 +354,7 @@ module SyntaxTree
|
|
354
354
|
body = parse_nested(lines[line_index..])
|
355
355
|
line_index += body.length
|
356
356
|
|
357
|
-
block_iseq = iseq.block_child_iseq(
|
357
|
+
block_iseq = iseq.block_child_iseq(1)
|
358
358
|
assemble_iseq(block_iseq, body)
|
359
359
|
block_iseq
|
360
360
|
end
|
data/lib/syntax_tree/yarv/bf.rb
CHANGED
@@ -13,7 +13,7 @@ module SyntaxTree
|
|
13
13
|
|
14
14
|
def compile
|
15
15
|
# Set up the top-level instruction sequence that will be returned.
|
16
|
-
iseq = InstructionSequence.new(
|
16
|
+
iseq = InstructionSequence.new("<compiled>", "<compiled>", 1, :top)
|
17
17
|
|
18
18
|
# Set up the $tape global variable that will hold our state.
|
19
19
|
iseq.duphash({ 0 => 0 })
|
@@ -80,19 +80,6 @@ module SyntaxTree
|
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
|
-
# This is the location of the top instruction sequence, derived from the
|
84
|
-
# source string.
|
85
|
-
def location
|
86
|
-
Location.new(
|
87
|
-
start_line: 1,
|
88
|
-
start_char: 0,
|
89
|
-
start_column: 0,
|
90
|
-
end_line: source.count("\n") + 1,
|
91
|
-
end_char: source.size,
|
92
|
-
end_column: source.size - (source.rindex("\n") || 0) - 1
|
93
|
-
)
|
94
|
-
end
|
95
|
-
|
96
83
|
# $tape[$cursor] += value
|
97
84
|
def change_by(iseq, value)
|
98
85
|
iseq.getglobal(:$tape)
|
@@ -111,6 +98,7 @@ module SyntaxTree
|
|
111
98
|
end
|
112
99
|
|
113
100
|
iseq.send(YARV.calldata(:[]=, 2))
|
101
|
+
iseq.pop
|
114
102
|
end
|
115
103
|
|
116
104
|
# $cursor += value
|
@@ -138,6 +126,7 @@ module SyntaxTree
|
|
138
126
|
iseq.send(YARV.calldata(:chr))
|
139
127
|
|
140
128
|
iseq.send(YARV.calldata(:putc, 1))
|
129
|
+
iseq.pop
|
141
130
|
end
|
142
131
|
|
143
132
|
# $tape[$cursor] = $stdin.getc.ord
|
@@ -150,6 +139,7 @@ module SyntaxTree
|
|
150
139
|
iseq.send(YARV.calldata(:ord))
|
151
140
|
|
152
141
|
iseq.send(YARV.calldata(:[]=, 2))
|
142
|
+
iseq.pop
|
153
143
|
end
|
154
144
|
|
155
145
|
# unless $tape[$cursor] == 0
|
@@ -164,14 +154,21 @@ module SyntaxTree
|
|
164
154
|
|
165
155
|
iseq.putobject(0)
|
166
156
|
iseq.send(YARV.calldata(:==, 1))
|
167
|
-
iseq.
|
157
|
+
iseq.branchif(end_label)
|
168
158
|
|
169
159
|
[start_label, end_label]
|
170
160
|
end
|
171
161
|
|
172
162
|
# Jump back to the start of the loop.
|
173
163
|
def loop_end(iseq, start_label, end_label)
|
174
|
-
iseq.
|
164
|
+
iseq.getglobal(:$tape)
|
165
|
+
iseq.getglobal(:$cursor)
|
166
|
+
iseq.send(YARV.calldata(:[], 1))
|
167
|
+
|
168
|
+
iseq.putobject(0)
|
169
|
+
iseq.send(YARV.calldata(:==, 1))
|
170
|
+
iseq.branchunless(start_label)
|
171
|
+
|
175
172
|
iseq.push(end_label)
|
176
173
|
end
|
177
174
|
end
|
@@ -304,10 +304,11 @@ module SyntaxTree
|
|
304
304
|
end
|
305
305
|
|
306
306
|
def visit_END(node)
|
307
|
+
start_line = node.location.start_line
|
307
308
|
once_iseq =
|
308
|
-
with_child_iseq(iseq.block_child_iseq(
|
309
|
+
with_child_iseq(iseq.block_child_iseq(start_line)) do
|
309
310
|
postexe_iseq =
|
310
|
-
with_child_iseq(iseq.block_child_iseq(
|
311
|
+
with_child_iseq(iseq.block_child_iseq(start_line)) do
|
311
312
|
iseq.event(:RUBY_EVENT_B_CALL)
|
312
313
|
|
313
314
|
*statements, last_statement = node.statements.body
|
@@ -567,7 +568,7 @@ module SyntaxTree
|
|
567
568
|
end
|
568
569
|
|
569
570
|
def visit_block(node)
|
570
|
-
with_child_iseq(iseq.block_child_iseq(node.location)) do
|
571
|
+
with_child_iseq(iseq.block_child_iseq(node.location.start_line)) do
|
571
572
|
iseq.event(:RUBY_EVENT_B_CALL)
|
572
573
|
visit(node.block_var)
|
573
574
|
visit(node.bodystmt)
|
@@ -751,7 +752,9 @@ module SyntaxTree
|
|
751
752
|
def visit_class(node)
|
752
753
|
name = node.constant.constant.value.to_sym
|
753
754
|
class_iseq =
|
754
|
-
with_child_iseq(
|
755
|
+
with_child_iseq(
|
756
|
+
iseq.class_child_iseq(name, node.location.start_line)
|
757
|
+
) do
|
755
758
|
iseq.event(:RUBY_EVENT_CLASS)
|
756
759
|
visit(node.bodystmt)
|
757
760
|
iseq.event(:RUBY_EVENT_END)
|
@@ -818,7 +821,8 @@ module SyntaxTree
|
|
818
821
|
|
819
822
|
def visit_def(node)
|
820
823
|
name = node.name.value.to_sym
|
821
|
-
method_iseq =
|
824
|
+
method_iseq =
|
825
|
+
iseq.method_child_iseq(name.to_s, node.location.start_line)
|
822
826
|
|
823
827
|
with_child_iseq(method_iseq) do
|
824
828
|
visit(node.params) if node.params
|
@@ -939,7 +943,9 @@ module SyntaxTree
|
|
939
943
|
iseq.local_table.plain(name)
|
940
944
|
|
941
945
|
block_iseq =
|
942
|
-
with_child_iseq(
|
946
|
+
with_child_iseq(
|
947
|
+
iseq.block_child_iseq(node.statements.location.start_line)
|
948
|
+
) do
|
943
949
|
iseq.argument_options[:lead_num] ||= 0
|
944
950
|
iseq.argument_options[:lead_num] += 1
|
945
951
|
iseq.argument_options[:ambiguous_param0] = true
|
@@ -1076,7 +1082,7 @@ module SyntaxTree
|
|
1076
1082
|
|
1077
1083
|
def visit_lambda(node)
|
1078
1084
|
lambda_iseq =
|
1079
|
-
with_child_iseq(iseq.block_child_iseq(node.location)) do
|
1085
|
+
with_child_iseq(iseq.block_child_iseq(node.location.start_line)) do
|
1080
1086
|
iseq.event(:RUBY_EVENT_B_CALL)
|
1081
1087
|
visit(node.params)
|
1082
1088
|
visit(node.statements)
|
@@ -1127,7 +1133,9 @@ module SyntaxTree
|
|
1127
1133
|
def visit_module(node)
|
1128
1134
|
name = node.constant.constant.value.to_sym
|
1129
1135
|
module_iseq =
|
1130
|
-
with_child_iseq(
|
1136
|
+
with_child_iseq(
|
1137
|
+
iseq.module_child_iseq(name, node.location.start_line)
|
1138
|
+
) do
|
1131
1139
|
iseq.event(:RUBY_EVENT_CLASS)
|
1132
1140
|
visit(node.bodystmt)
|
1133
1141
|
iseq.event(:RUBY_EVENT_END)
|
@@ -1375,10 +1383,11 @@ module SyntaxTree
|
|
1375
1383
|
|
1376
1384
|
top_iseq =
|
1377
1385
|
InstructionSequence.new(
|
1378
|
-
:top,
|
1379
1386
|
"<compiled>",
|
1387
|
+
"<compiled>",
|
1388
|
+
1,
|
1389
|
+
:top,
|
1380
1390
|
nil,
|
1381
|
-
node.location,
|
1382
1391
|
options
|
1383
1392
|
)
|
1384
1393
|
|
@@ -1543,7 +1552,9 @@ module SyntaxTree
|
|
1543
1552
|
iseq.putnil
|
1544
1553
|
|
1545
1554
|
singleton_iseq =
|
1546
|
-
with_child_iseq(
|
1555
|
+
with_child_iseq(
|
1556
|
+
iseq.singleton_class_child_iseq(node.location.start_line)
|
1557
|
+
) do
|
1547
1558
|
iseq.event(:RUBY_EVENT_CLASS)
|
1548
1559
|
visit(node.bodystmt)
|
1549
1560
|
iseq.event(:RUBY_EVENT_END)
|
@@ -2018,7 +2029,7 @@ module SyntaxTree
|
|
2018
2029
|
if node.constant
|
2019
2030
|
iseq.dup
|
2020
2031
|
visit(node.constant)
|
2021
|
-
iseq.checkmatch(CheckMatch::
|
2032
|
+
iseq.checkmatch(CheckMatch::VM_CHECKMATCH_TYPE_CASE)
|
2022
2033
|
iseq.branchunless(match_failure_label)
|
2023
2034
|
end
|
2024
2035
|
|
@@ -2078,7 +2089,7 @@ module SyntaxTree
|
|
2078
2089
|
iseq.setlocal(lookup.index, lookup.level)
|
2079
2090
|
else
|
2080
2091
|
visit(required)
|
2081
|
-
iseq.checkmatch(CheckMatch::
|
2092
|
+
iseq.checkmatch(CheckMatch::VM_CHECKMATCH_TYPE_CASE)
|
2082
2093
|
iseq.branchunless(match_failure_label)
|
2083
2094
|
end
|
2084
2095
|
|
@@ -64,6 +64,13 @@ module SyntaxTree
|
|
64
64
|
clauses[label] = clause
|
65
65
|
clause = []
|
66
66
|
label = insn.name
|
67
|
+
when BranchIf
|
68
|
+
body = [
|
69
|
+
Assign(block_label.field, node_for(insn.label.name)),
|
70
|
+
Next(Args([]))
|
71
|
+
]
|
72
|
+
|
73
|
+
clause << UnlessNode(clause.pop, Statements(body), nil)
|
67
74
|
when BranchUnless
|
68
75
|
body = [
|
69
76
|
Assign(block_label.field, node_for(insn.label.name)),
|
@@ -157,6 +164,8 @@ module SyntaxTree
|
|
157
164
|
)
|
158
165
|
end
|
159
166
|
end
|
167
|
+
when Pop
|
168
|
+
# skip
|
160
169
|
when PutObject
|
161
170
|
case insn.object
|
162
171
|
when Float
|
@@ -4,7 +4,8 @@ module SyntaxTree
|
|
4
4
|
module YARV
|
5
5
|
class Disassembler
|
6
6
|
attr_reader :output, :queue
|
7
|
-
attr_reader :current_prefix
|
7
|
+
attr_reader :current_prefix
|
8
|
+
attr_accessor :current_iseq
|
8
9
|
|
9
10
|
def initialize
|
10
11
|
@output = StringIO.new
|
@@ -114,7 +115,7 @@ module SyntaxTree
|
|
114
115
|
output << "#{current_prefix}== disasm: "
|
115
116
|
output << "#<ISeq:#{iseq.name}@<compiled>:1 "
|
116
117
|
|
117
|
-
location = iseq.
|
118
|
+
location = Location.fixed(line: iseq.line, char: 0, column: 0)
|
118
119
|
output << "(#{location.start_line},#{location.start_column})-"
|
119
120
|
output << "(#{location.end_line},#{location.end_column})"
|
120
121
|
output << "> "
|