syntax_tree 5.0.1 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,215 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ module YARV
5
+ # This module contains the instructions that used to be a part of YARV but
6
+ # have been replaced or removed in more recent versions.
7
+ module Legacy
8
+ # ### Summary
9
+ #
10
+ # `getclassvariable` looks for a class variable in the current class and
11
+ # pushes its value onto the stack.
12
+ #
13
+ # This version of the `getclassvariable` instruction is no longer used
14
+ # since in Ruby 3.0 it gained an inline cache.`
15
+ #
16
+ # ### Usage
17
+ #
18
+ # ~~~ruby
19
+ # @@class_variable
20
+ # ~~~
21
+ #
22
+ class GetClassVariable
23
+ attr_reader :name
24
+
25
+ def initialize(name)
26
+ @name = name
27
+ end
28
+
29
+ def disasm(fmt)
30
+ fmt.instruction("getclassvariable", [fmt.object(name)])
31
+ end
32
+
33
+ def to_a(_iseq)
34
+ [:getclassvariable, name]
35
+ end
36
+
37
+ def length
38
+ 2
39
+ end
40
+
41
+ def pops
42
+ 0
43
+ end
44
+
45
+ def pushes
46
+ 1
47
+ end
48
+
49
+ def canonical
50
+ YARV::GetClassVariable.new(name, nil)
51
+ end
52
+
53
+ def call(vm)
54
+ canonical.call(vm)
55
+ end
56
+ end
57
+
58
+ # ### Summary
59
+ #
60
+ # `opt_getinlinecache` is a wrapper around a series of `putobject` and
61
+ # `getconstant` instructions that allows skipping past them if the inline
62
+ # cache is currently set. It pushes the value of the cache onto the stack
63
+ # if it is set, otherwise it pushes `nil`.
64
+ #
65
+ # This instruction is no longer used since in Ruby 3.2 it was replaced by
66
+ # the consolidated `opt_getconstant_path` instruction.
67
+ #
68
+ # ### Usage
69
+ #
70
+ # ~~~ruby
71
+ # Constant
72
+ # ~~~
73
+ #
74
+ class OptGetInlineCache
75
+ attr_reader :label, :cache
76
+
77
+ def initialize(label, cache)
78
+ @label = label
79
+ @cache = cache
80
+ end
81
+
82
+ def disasm(fmt)
83
+ fmt.instruction(
84
+ "opt_getinlinecache",
85
+ [fmt.label(label), fmt.inline_storage(cache)]
86
+ )
87
+ end
88
+
89
+ def to_a(_iseq)
90
+ [:opt_getinlinecache, label.name, cache]
91
+ end
92
+
93
+ def length
94
+ 3
95
+ end
96
+
97
+ def pops
98
+ 0
99
+ end
100
+
101
+ def pushes
102
+ 1
103
+ end
104
+
105
+ def canonical
106
+ self
107
+ end
108
+
109
+ def call(vm)
110
+ vm.push(nil)
111
+ end
112
+ end
113
+
114
+ # ### Summary
115
+ #
116
+ # `opt_setinlinecache` sets an inline cache for a constant lookup. It pops
117
+ # the value it should set off the top of the stack. It uses this value to
118
+ # set the cache. It then pushes that value back onto the top of the stack.
119
+ #
120
+ # This instruction is no longer used since in Ruby 3.2 it was replaced by
121
+ # the consolidated `opt_getconstant_path` instruction.
122
+ #
123
+ # ### Usage
124
+ #
125
+ # ~~~ruby
126
+ # Constant
127
+ # ~~~
128
+ #
129
+ class OptSetInlineCache
130
+ attr_reader :cache
131
+
132
+ def initialize(cache)
133
+ @cache = cache
134
+ end
135
+
136
+ def disasm(fmt)
137
+ fmt.instruction("opt_setinlinecache", [fmt.inline_storage(cache)])
138
+ end
139
+
140
+ def to_a(_iseq)
141
+ [:opt_setinlinecache, cache]
142
+ end
143
+
144
+ def length
145
+ 2
146
+ end
147
+
148
+ def pops
149
+ 1
150
+ end
151
+
152
+ def pushes
153
+ 1
154
+ end
155
+
156
+ def canonical
157
+ self
158
+ end
159
+
160
+ def call(vm)
161
+ end
162
+ end
163
+
164
+ # ### Summary
165
+ #
166
+ # `setclassvariable` looks for a class variable in the current class and
167
+ # sets its value to the value it pops off the top of the stack.
168
+ #
169
+ # This version of the `setclassvariable` instruction is no longer used
170
+ # since in Ruby 3.0 it gained an inline cache.
171
+ #
172
+ # ### Usage
173
+ #
174
+ # ~~~ruby
175
+ # @@class_variable = 1
176
+ # ~~~
177
+ #
178
+ class SetClassVariable
179
+ attr_reader :name
180
+
181
+ def initialize(name)
182
+ @name = name
183
+ end
184
+
185
+ def disasm(fmt)
186
+ fmt.instruction("setclassvariable", [fmt.object(name)])
187
+ end
188
+
189
+ def to_a(_iseq)
190
+ [:setclassvariable, name]
191
+ end
192
+
193
+ def length
194
+ 2
195
+ end
196
+
197
+ def pops
198
+ 1
199
+ end
200
+
201
+ def pushes
202
+ 0
203
+ end
204
+
205
+ def canonical
206
+ YARV::SetClassVariable.new(name, nil)
207
+ end
208
+
209
+ def call(vm)
210
+ canonical.call(vm)
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ module YARV
5
+ # This represents every local variable associated with an instruction
6
+ # sequence. There are two kinds of locals: plain locals that are what you
7
+ # expect, and block proxy locals, which represent local variables
8
+ # associated with blocks that were passed into the current instruction
9
+ # sequence.
10
+ class LocalTable
11
+ # A local representing a block passed into the current instruction
12
+ # sequence.
13
+ class BlockLocal
14
+ attr_reader :name
15
+
16
+ def initialize(name)
17
+ @name = name
18
+ end
19
+ end
20
+
21
+ # A regular local variable.
22
+ class PlainLocal
23
+ attr_reader :name
24
+
25
+ def initialize(name)
26
+ @name = name
27
+ end
28
+ end
29
+
30
+ # The result of looking up a local variable in the current local table.
31
+ class Lookup
32
+ attr_reader :local, :index, :level
33
+
34
+ def initialize(local, index, level)
35
+ @local = local
36
+ @index = index
37
+ @level = level
38
+ end
39
+ end
40
+
41
+ attr_reader :locals
42
+
43
+ def initialize
44
+ @locals = []
45
+ end
46
+
47
+ def empty?
48
+ locals.empty?
49
+ end
50
+
51
+ def find(name, level = 0)
52
+ index = locals.index { |local| local.name == name }
53
+ Lookup.new(locals[index], index, level) if index
54
+ end
55
+
56
+ def has?(name)
57
+ locals.any? { |local| local.name == name }
58
+ end
59
+
60
+ def names
61
+ locals.map(&:name)
62
+ end
63
+
64
+ def name_at(index)
65
+ locals[index].name
66
+ end
67
+
68
+ def size
69
+ locals.length
70
+ end
71
+
72
+ # Add a BlockLocal to the local table.
73
+ def block(name)
74
+ locals << BlockLocal.new(name) unless has?(name)
75
+ end
76
+
77
+ # Add a PlainLocal to the local table.
78
+ def plain(name)
79
+ locals << PlainLocal.new(name) unless has?(name)
80
+ end
81
+
82
+ # This is the offset from the top of the stack where this local variable
83
+ # lives.
84
+ def offset(index)
85
+ size - (index - 3) - 1
86
+ end
87
+ end
88
+ end
89
+ end