steep 0.47.1 → 0.48.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +6 -6
- data/lib/steep/ast/types/factory.rb +161 -137
- data/lib/steep/ast/types/var.rb +14 -3
- data/lib/steep/diagnostic/ruby.rb +23 -11
- data/lib/steep/diagnostic/signature.rb +56 -0
- data/lib/steep/interface/method_type.rb +14 -26
- data/lib/steep/interface/type_param.rb +103 -0
- data/lib/steep/server/base_worker.rb +1 -0
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/type_check_worker.rb +2 -2
- data/lib/steep/services/signature_service.rb +2 -2
- data/lib/steep/services/type_check_service.rb +2 -1
- data/lib/steep/signature/validator.rb +221 -49
- data/lib/steep/subtyping/cache.rb +30 -0
- data/lib/steep/subtyping/check.rb +582 -708
- data/lib/steep/subtyping/constraints.rb +66 -30
- data/lib/steep/subtyping/relation.rb +60 -0
- data/lib/steep/subtyping/result.rb +190 -16
- data/lib/steep/type_construction.rb +492 -371
- data/lib/steep/type_inference/context.rb +37 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +3 -3
- data/sample/lib/length.rb +35 -0
- data/sample/sig/length.rbs +34 -0
- data/smoke/diagnostics-rbs/nonregular-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/recursive-type-alias.rbs +3 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +57 -12
- data/steep.gemspec +1 -1
- metadata +13 -10
- data/lib/steep/drivers/trace_printer.rb +0 -29
- data/lib/steep/interface/method.rb +0 -78
- data/lib/steep/subtyping/trace.rb +0 -71
@@ -102,6 +102,36 @@ module Steep
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
+
class TypeVariableContext
|
106
|
+
attr_reader :table
|
107
|
+
attr_reader :type_params
|
108
|
+
|
109
|
+
def initialize(type_params, parent_context: nil)
|
110
|
+
@type_params = type_params
|
111
|
+
|
112
|
+
@table = {}
|
113
|
+
table.merge!(parent_context.table) if parent_context
|
114
|
+
|
115
|
+
type_params.each do |param|
|
116
|
+
table[param.name] = param
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def [](name)
|
121
|
+
table[name].upper_bound
|
122
|
+
end
|
123
|
+
|
124
|
+
def upper_bounds
|
125
|
+
table.each_value.with_object({}) do |type_param, bounds|
|
126
|
+
bounds[type_param.name] = type_param.upper_bound
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.empty
|
131
|
+
new([])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
105
135
|
attr_reader :call_context
|
106
136
|
attr_reader :method_context
|
107
137
|
attr_reader :block_context
|
@@ -110,8 +140,9 @@ module Steep
|
|
110
140
|
attr_reader :self_type
|
111
141
|
attr_reader :type_env
|
112
142
|
attr_reader :lvar_env
|
143
|
+
attr_reader :variable_context
|
113
144
|
|
114
|
-
def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:)
|
145
|
+
def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:, variable_context:)
|
115
146
|
@method_context = method_context
|
116
147
|
@block_context = block_context
|
117
148
|
@break_context = break_context
|
@@ -120,6 +151,7 @@ module Steep
|
|
120
151
|
@type_env = type_env
|
121
152
|
@lvar_env = lvar_env
|
122
153
|
@call_context = call_context
|
154
|
+
@variable_context = variable_context
|
123
155
|
end
|
124
156
|
|
125
157
|
def with(method_context: self.method_context,
|
@@ -129,7 +161,8 @@ module Steep
|
|
129
161
|
self_type: self.self_type,
|
130
162
|
type_env: self.type_env,
|
131
163
|
lvar_env: self.lvar_env,
|
132
|
-
call_context: self.call_context
|
164
|
+
call_context: self.call_context,
|
165
|
+
variable_context: self.variable_context)
|
133
166
|
self.class.new(
|
134
167
|
method_context: method_context,
|
135
168
|
block_context: block_context,
|
@@ -138,7 +171,8 @@ module Steep
|
|
138
171
|
self_type: self_type,
|
139
172
|
type_env: type_env,
|
140
173
|
lvar_env: lvar_env,
|
141
|
-
call_context: call_context
|
174
|
+
call_context: call_context,
|
175
|
+
variable_context: variable_context
|
142
176
|
)
|
143
177
|
end
|
144
178
|
end
|
data/lib/steep/version.rb
CHANGED
data/lib/steep.rb
CHANGED
@@ -50,16 +50,17 @@ require "steep/ast/types/factory"
|
|
50
50
|
|
51
51
|
require "steep/range_extension"
|
52
52
|
|
53
|
+
require "steep/interface/type_param"
|
53
54
|
require "steep/interface/function"
|
54
55
|
require "steep/interface/block"
|
55
56
|
require "steep/interface/method_type"
|
56
57
|
require "steep/interface/substitution"
|
57
58
|
require "steep/interface/interface"
|
58
59
|
|
59
|
-
require "steep/subtyping/check"
|
60
60
|
require "steep/subtyping/result"
|
61
|
+
require "steep/subtyping/check"
|
62
|
+
require "steep/subtyping/cache"
|
61
63
|
require "steep/subtyping/relation"
|
62
|
-
require "steep/subtyping/trace"
|
63
64
|
require "steep/subtyping/constraints"
|
64
65
|
require "steep/subtyping/variable_variance"
|
65
66
|
require "steep/subtyping/variable_occurrence"
|
@@ -123,7 +124,6 @@ require "steep/drivers/validate"
|
|
123
124
|
require "steep/drivers/annotations"
|
124
125
|
require "steep/drivers/watch"
|
125
126
|
require "steep/drivers/langserver"
|
126
|
-
require "steep/drivers/trace_printer"
|
127
127
|
require "steep/drivers/print_project"
|
128
128
|
require "steep/drivers/init"
|
129
129
|
require "steep/drivers/vendor"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class LengthCalculator
|
2
|
+
def max0(x, y)
|
3
|
+
if x.size > y.size
|
4
|
+
x
|
5
|
+
else
|
6
|
+
y
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def max1(x, y)
|
11
|
+
if x.size > y.size
|
12
|
+
x
|
13
|
+
else
|
14
|
+
y
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def max2(x, y)
|
19
|
+
if x.size > y.size
|
20
|
+
x
|
21
|
+
else
|
22
|
+
y
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
calc = LengthCalculator.new()
|
28
|
+
|
29
|
+
calc.max0("foo", "bar")
|
30
|
+
calc.max1("foo", "bar")
|
31
|
+
calc.max2("foo", "bar")
|
32
|
+
|
33
|
+
calc.max0(true, false)
|
34
|
+
calc.max1(true, false)
|
35
|
+
calc.max2(true, false)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# LengthCalculator shows three different method types having the same implementation.
|
2
|
+
#
|
3
|
+
# * It receives two objects.
|
4
|
+
# * It calls the `#size` method of the objects, and compare the return values.
|
5
|
+
# * It returns one of the objects which has bigger `#size` value.
|
6
|
+
#
|
7
|
+
class LengthCalculator
|
8
|
+
interface _Sized
|
9
|
+
def size: () -> Integer
|
10
|
+
end
|
11
|
+
|
12
|
+
# *Untyped* version -- all (static) type information is lost.
|
13
|
+
#
|
14
|
+
# You can pass any object, even if the object doesn't have `#size` method.
|
15
|
+
#
|
16
|
+
def max0: (untyped, untyped) -> untyped
|
17
|
+
|
18
|
+
# *Subtyping* version -- with constraints on arguments, but the return type is inaccurate.
|
19
|
+
#
|
20
|
+
# You can type check if the object has `#size` method of the expected type.
|
21
|
+
# However, the return type also has `_Sized` type, which drops other methods than `#size`.
|
22
|
+
#
|
23
|
+
def max1: (_Sized, _Sized) -> _Sized
|
24
|
+
|
25
|
+
# *Generics* version -- the most advanced one in Steep/RBS
|
26
|
+
#
|
27
|
+
# You can type check if the object has `#size` method of the expected type.
|
28
|
+
# And the return type is the one given as arguments.
|
29
|
+
#
|
30
|
+
# Note that the type system of Steep cannot ensure the given two objects have the same type.
|
31
|
+
# Passing `String` and `Array[String]` will infer the return type `String | Array[String]`.
|
32
|
+
#
|
33
|
+
def max2: [T < _Sized] (T, T) -> T
|
34
|
+
end
|
@@ -103,6 +103,31 @@
|
|
103
103
|
message: The variance of type parameter `A` is covariant, but used in incompatible
|
104
104
|
position here
|
105
105
|
code: RBS::InvalidVarianceAnnotation
|
106
|
+
- file: mixin-class-error.rbs
|
107
|
+
diagnostics:
|
108
|
+
- range:
|
109
|
+
start:
|
110
|
+
line: 5
|
111
|
+
character: 2
|
112
|
+
end:
|
113
|
+
line: 5
|
114
|
+
character: 13
|
115
|
+
severity: ERROR
|
116
|
+
message: Cannot include a class `::Foo` in the definition of `::Bar`
|
117
|
+
code: RBS::MixinClassError
|
118
|
+
- file: nonregular-type-alias.rbs
|
119
|
+
diagnostics:
|
120
|
+
- range:
|
121
|
+
start:
|
122
|
+
line: 2
|
123
|
+
character: 2
|
124
|
+
end:
|
125
|
+
line: 2
|
126
|
+
character: 42
|
127
|
+
severity: ERROR
|
128
|
+
message: 'Type alias ::NonregularTypeAlias::t is defined *non-regular*: ::NonregularTypeAlias::t[::String,
|
129
|
+
::Integer]'
|
130
|
+
code: RBS::NonregularTypeAlias
|
106
131
|
- file: recursive-alias.rbs
|
107
132
|
diagnostics:
|
108
133
|
- range:
|
@@ -151,6 +176,38 @@
|
|
151
176
|
message: 'Circular inheritance/mix-in is detected: ::Baz <: ::Foo <: ::Bar <:
|
152
177
|
::Baz'
|
153
178
|
code: RBS::RecursiveAncestor
|
179
|
+
- file: recursive-type-alias.rbs
|
180
|
+
diagnostics:
|
181
|
+
- range:
|
182
|
+
start:
|
183
|
+
line: 1
|
184
|
+
character: 0
|
185
|
+
end:
|
186
|
+
line: 1
|
187
|
+
character: 14
|
188
|
+
severity: ERROR
|
189
|
+
message: 'Type aliases cannot be *directly recursive*: ::foo'
|
190
|
+
code: RBS::RecursiveTypeAlias
|
191
|
+
- range:
|
192
|
+
start:
|
193
|
+
line: 2
|
194
|
+
character: 0
|
195
|
+
end:
|
196
|
+
line: 2
|
197
|
+
character: 14
|
198
|
+
severity: ERROR
|
199
|
+
message: 'Type aliases cannot be *directly recursive*: ::bar'
|
200
|
+
code: RBS::RecursiveTypeAlias
|
201
|
+
- range:
|
202
|
+
start:
|
203
|
+
line: 3
|
204
|
+
character: 0
|
205
|
+
end:
|
206
|
+
line: 3
|
207
|
+
character: 14
|
208
|
+
severity: ERROR
|
209
|
+
message: 'Type aliases cannot be *directly recursive*: ::baz'
|
210
|
+
code: RBS::RecursiveTypeAlias
|
154
211
|
- file: superclass-mismatch.rbs
|
155
212
|
diagnostics:
|
156
213
|
- range:
|
@@ -229,15 +286,3 @@
|
|
229
286
|
severity: ERROR
|
230
287
|
message: Cannot find type `ZZZ`
|
231
288
|
code: RBS::UnknownTypeName
|
232
|
-
- file: mixin-class-error.rbs
|
233
|
-
diagnostics:
|
234
|
-
- range:
|
235
|
-
start:
|
236
|
-
line: 5
|
237
|
-
character: 2
|
238
|
-
end:
|
239
|
-
line: 5
|
240
|
-
character: 13
|
241
|
-
severity: ERROR
|
242
|
-
message: Cannot include a class `::Foo` in the definition of `::Bar`
|
243
|
-
code: RBS::MixinClassError
|
data/steep.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_runtime_dependency "rainbow", ">= 2.2.2", "< 4.0"
|
34
34
|
spec.add_runtime_dependency "listen", "~> 3.0"
|
35
35
|
spec.add_runtime_dependency "language_server-protocol", ">= 3.15", "< 4.0"
|
36
|
-
spec.add_runtime_dependency "rbs", "
|
36
|
+
spec.add_runtime_dependency "rbs", ">= 2.2.0"
|
37
37
|
spec.add_runtime_dependency "parallel", ">= 1.0.0"
|
38
38
|
spec.add_runtime_dependency "terminal-table", ">= 2", "< 4"
|
39
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.48.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -96,16 +96,16 @@ dependencies:
|
|
96
96
|
name: rbs
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
98
98
|
requirements:
|
99
|
-
- - "
|
99
|
+
- - ">="
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
101
|
+
version: 2.2.0
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
|
-
- - "
|
106
|
+
- - ">="
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
108
|
+
version: 2.2.0
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
110
|
name: parallel
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,7 +204,6 @@ files:
|
|
204
204
|
- lib/steep/drivers/langserver.rb
|
205
205
|
- lib/steep/drivers/print_project.rb
|
206
206
|
- lib/steep/drivers/stats.rb
|
207
|
-
- lib/steep/drivers/trace_printer.rb
|
208
207
|
- lib/steep/drivers/utils/driver_helper.rb
|
209
208
|
- lib/steep/drivers/utils/jobs_count.rb
|
210
209
|
- lib/steep/drivers/validate.rb
|
@@ -219,9 +218,9 @@ files:
|
|
219
218
|
- lib/steep/interface/block.rb
|
220
219
|
- lib/steep/interface/function.rb
|
221
220
|
- lib/steep/interface/interface.rb
|
222
|
-
- lib/steep/interface/method.rb
|
223
221
|
- lib/steep/interface/method_type.rb
|
224
222
|
- lib/steep/interface/substitution.rb
|
223
|
+
- lib/steep/interface/type_param.rb
|
225
224
|
- lib/steep/method_name.rb
|
226
225
|
- lib/steep/module_helper.rb
|
227
226
|
- lib/steep/project.rb
|
@@ -247,11 +246,11 @@ files:
|
|
247
246
|
- lib/steep/services/type_check_service.rb
|
248
247
|
- lib/steep/signature/validator.rb
|
249
248
|
- lib/steep/source.rb
|
249
|
+
- lib/steep/subtyping/cache.rb
|
250
250
|
- lib/steep/subtyping/check.rb
|
251
251
|
- lib/steep/subtyping/constraints.rb
|
252
252
|
- lib/steep/subtyping/relation.rb
|
253
253
|
- lib/steep/subtyping/result.rb
|
254
|
-
- lib/steep/subtyping/trace.rb
|
255
254
|
- lib/steep/subtyping/variable_occurrence.rb
|
256
255
|
- lib/steep/subtyping/variable_variance.rb
|
257
256
|
- lib/steep/type_construction.rb
|
@@ -271,7 +270,9 @@ files:
|
|
271
270
|
- manual/annotations.md
|
272
271
|
- sample/Steepfile
|
273
272
|
- sample/lib/conference.rb
|
273
|
+
- sample/lib/length.rb
|
274
274
|
- sample/sig/conference.rbs
|
275
|
+
- sample/sig/length.rbs
|
275
276
|
- smoke/alias/Steepfile
|
276
277
|
- smoke/alias/a.rb
|
277
278
|
- smoke/alias/a.rbs
|
@@ -324,8 +325,10 @@ files:
|
|
324
325
|
- smoke/diagnostics-rbs/invalid-type-application.rbs
|
325
326
|
- smoke/diagnostics-rbs/invalid_variance_annotation.rbs
|
326
327
|
- smoke/diagnostics-rbs/mixin-class-error.rbs
|
328
|
+
- smoke/diagnostics-rbs/nonregular-type-alias.rbs
|
327
329
|
- smoke/diagnostics-rbs/recursive-alias.rbs
|
328
330
|
- smoke/diagnostics-rbs/recursive-class.rbs
|
331
|
+
- smoke/diagnostics-rbs/recursive-type-alias.rbs
|
329
332
|
- smoke/diagnostics-rbs/superclass-mismatch.rbs
|
330
333
|
- smoke/diagnostics-rbs/test_expectations.yml
|
331
334
|
- smoke/diagnostics-rbs/unknown-method-alias.rbs
|
@@ -533,7 +536,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
533
536
|
- !ruby/object:Gem::Version
|
534
537
|
version: '0'
|
535
538
|
requirements: []
|
536
|
-
rubygems_version: 3.3.
|
539
|
+
rubygems_version: 3.3.7
|
537
540
|
signing_key:
|
538
541
|
specification_version: 4
|
539
542
|
summary: Gradual Typing for Ruby
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Steep
|
2
|
-
module Drivers
|
3
|
-
class TracePrinter
|
4
|
-
attr_reader :io
|
5
|
-
|
6
|
-
def initialize(io)
|
7
|
-
@io = io
|
8
|
-
end
|
9
|
-
|
10
|
-
def print(trace, level: 0)
|
11
|
-
trace.each.with_index do |t, i|
|
12
|
-
prefix = " " * (i + level)
|
13
|
-
case t[0]
|
14
|
-
when :type
|
15
|
-
io.puts "#{prefix}#{t[1]} <: #{t[2]}"
|
16
|
-
when :method
|
17
|
-
io.puts "#{prefix}(#{t[3]}) #{t[1]} <: #{t[2]}"
|
18
|
-
when :method_type
|
19
|
-
io.puts "#{prefix}#{t[1]} <: #{t[2]}"
|
20
|
-
when :interface
|
21
|
-
# nop
|
22
|
-
else
|
23
|
-
Steep.logger.error { "Unexpected trace item: #{t[0]}" }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module Steep
|
2
|
-
module Interface
|
3
|
-
class Method
|
4
|
-
attr_reader :type_name
|
5
|
-
attr_reader :name
|
6
|
-
attr_reader :super_method
|
7
|
-
attr_reader :types
|
8
|
-
attr_reader :attributes
|
9
|
-
|
10
|
-
def initialize(type_name:, name:, types:, super_method:, attributes:)
|
11
|
-
@type_name = type_name
|
12
|
-
@name = name
|
13
|
-
@types = types
|
14
|
-
@super_method = super_method
|
15
|
-
@attributes = attributes
|
16
|
-
end
|
17
|
-
|
18
|
-
def ==(other)
|
19
|
-
other.is_a?(Method) &&
|
20
|
-
other.type_name == type_name &&
|
21
|
-
other.name == name &&
|
22
|
-
other.types == types &&
|
23
|
-
other.super_method == super_method &&
|
24
|
-
other.attributes == attributes
|
25
|
-
end
|
26
|
-
|
27
|
-
def private?
|
28
|
-
attributes.include?(:private)
|
29
|
-
end
|
30
|
-
|
31
|
-
def closed?
|
32
|
-
types.all?(&:closed?)
|
33
|
-
end
|
34
|
-
|
35
|
-
def subst(s)
|
36
|
-
self.class.new(
|
37
|
-
type_name: type_name,
|
38
|
-
name: name,
|
39
|
-
types: types.map {|type| type.subst(s) },
|
40
|
-
super_method: super_method&.subst(s),
|
41
|
-
attributes: attributes
|
42
|
-
)
|
43
|
-
end
|
44
|
-
|
45
|
-
def with_super(super_method)
|
46
|
-
self.class.new(
|
47
|
-
type_name: type_name,
|
48
|
-
name: name,
|
49
|
-
types: types,
|
50
|
-
super_method: super_method,
|
51
|
-
attributes: attributes
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
def with_types(types)
|
56
|
-
self.class.new(
|
57
|
-
type_name: type_name,
|
58
|
-
name: name,
|
59
|
-
types: types,
|
60
|
-
super_method: super_method,
|
61
|
-
attributes: attributes
|
62
|
-
)
|
63
|
-
end
|
64
|
-
|
65
|
-
def map_types
|
66
|
-
with_types(types.map {|type| yield type })
|
67
|
-
end
|
68
|
-
|
69
|
-
def include_in_chain?(method)
|
70
|
-
(method.type_name == type_name &&
|
71
|
-
method.name == name &&
|
72
|
-
method.types == types &&
|
73
|
-
method.attributes == attributes) ||
|
74
|
-
super_method&.include_in_chain?(method)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Steep
|
2
|
-
module Subtyping
|
3
|
-
class Trace
|
4
|
-
attr_reader :array
|
5
|
-
|
6
|
-
def initialize(array: [])
|
7
|
-
@array = array
|
8
|
-
end
|
9
|
-
|
10
|
-
def interface(sub, sup, &block)
|
11
|
-
push :interface, sub, sup, &block
|
12
|
-
end
|
13
|
-
|
14
|
-
def method(name, sub, sup, &block)
|
15
|
-
push :method, sub, sup, name, &block
|
16
|
-
end
|
17
|
-
|
18
|
-
def method_type(name, sub, sup, &block)
|
19
|
-
push :method_type, sub, sup, name, &block
|
20
|
-
end
|
21
|
-
|
22
|
-
def type(sub, sup, &block)
|
23
|
-
push :type, sub, sup, &block
|
24
|
-
end
|
25
|
-
|
26
|
-
def push(*xs)
|
27
|
-
array << xs
|
28
|
-
yield
|
29
|
-
ensure
|
30
|
-
array.pop
|
31
|
-
end
|
32
|
-
|
33
|
-
def add(sup, sub)
|
34
|
-
array << [sup, sub]
|
35
|
-
yield
|
36
|
-
ensure
|
37
|
-
array.pop
|
38
|
-
end
|
39
|
-
|
40
|
-
def empty?
|
41
|
-
array.empty?
|
42
|
-
end
|
43
|
-
|
44
|
-
def drop(n)
|
45
|
-
self.class.new(array: array.drop(n))
|
46
|
-
end
|
47
|
-
|
48
|
-
def size
|
49
|
-
array.size
|
50
|
-
end
|
51
|
-
|
52
|
-
def +(other)
|
53
|
-
self.class.new(array: array + other.array)
|
54
|
-
end
|
55
|
-
|
56
|
-
def initialize_copy(source)
|
57
|
-
@array = source.array.dup
|
58
|
-
end
|
59
|
-
|
60
|
-
def each
|
61
|
-
if block_given?
|
62
|
-
array.each do |pair|
|
63
|
-
yield(*pair)
|
64
|
-
end
|
65
|
-
else
|
66
|
-
enum_for :each
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|