rbs 0.16.0 → 0.20.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/README.md +1 -1
  5. data/Rakefile +12 -1
  6. data/core/array.rbs +1 -1
  7. data/core/builtin.rbs +2 -2
  8. data/core/dir.rbs +1 -1
  9. data/core/enumerable.rbs +41 -40
  10. data/core/enumerator.rbs +5 -5
  11. data/core/file.rbs +0 -4
  12. data/core/hash.rbs +9 -11
  13. data/core/io.rbs +1 -1
  14. data/core/object_space.rbs +98 -0
  15. data/core/range.rbs +1 -1
  16. data/core/struct.rbs +1 -1
  17. data/core/time.rbs +0 -12
  18. data/lib/rbs/ast/members.rb +9 -3
  19. data/lib/rbs/definition.rb +9 -4
  20. data/lib/rbs/definition_builder.rb +123 -71
  21. data/lib/rbs/environment.rb +3 -0
  22. data/lib/rbs/environment_loader.rb +1 -1
  23. data/lib/rbs/environment_walker.rb +70 -35
  24. data/lib/rbs/method_type.rb +1 -31
  25. data/lib/rbs/parser.rb +944 -879
  26. data/lib/rbs/parser.y +110 -63
  27. data/lib/rbs/prototype/rb.rb +163 -23
  28. data/lib/rbs/prototype/rbi.rb +5 -5
  29. data/lib/rbs/prototype/runtime.rb +2 -1
  30. data/lib/rbs/test/hook.rb +30 -17
  31. data/lib/rbs/test/type_check.rb +6 -1
  32. data/lib/rbs/types.rb +63 -6
  33. data/lib/rbs/version.rb +1 -1
  34. data/lib/rbs/writer.rb +9 -1
  35. data/schema/members.json +5 -1
  36. data/sig/definition.rbs +8 -3
  37. data/sig/definition_builder.rbs +6 -2
  38. data/sig/members.rbs +4 -1
  39. data/sig/method_types.rbs +3 -16
  40. data/sig/types.rbs +17 -1
  41. data/stdlib/csv/0/csv.rbs +3 -3
  42. data/stdlib/dbm/0/dbm.rbs +1 -3
  43. data/stdlib/monitor/0/monitor.rbs +119 -0
  44. data/stdlib/prime/0/prime.rbs +1 -1
  45. data/stdlib/set/0/set.rbs +10 -10
  46. data/stdlib/singleton/0/singleton.rbs +111 -0
  47. data/stdlib/tsort/0/cyclic.rbs +4 -0
  48. data/stdlib/tsort/0/interfaces.rbs +19 -0
  49. data/stdlib/tsort/0/tsort.rbs +371 -0
  50. data/stdlib/yaml/0/dbm.rbs +221 -0
  51. data/stdlib/yaml/0/store.rbs +53 -0
  52. data/steep/Gemfile.lock +12 -12
  53. metadata +11 -3
@@ -334,11 +334,27 @@ module RBS
334
334
  def has_keyword?: () -> bool
335
335
  end
336
336
 
337
+ class Block
338
+ attr_reader type: Types::Function
339
+ attr_reader required: boolish
340
+
341
+ def initialize: (type: Types::Function, required: boolish) -> void
342
+
343
+ def ==: (untyped other) -> bool
344
+
345
+ def to_json: (*untyped) -> String
346
+
347
+ def sub: (Substitution) -> Block
348
+
349
+ def map_type: () { (Types::t) -> Types::t } -> Block
350
+ end
351
+
337
352
  class Proc
338
353
  attr_reader type: Function
354
+ attr_reader block: Block?
339
355
  attr_reader location: Location?
340
356
 
341
- def initialize: (location: Location?, type: Function) -> void
357
+ def initialize: (location: Location?, type: Function, block: Block?) -> void
342
358
 
343
359
  include _TypeBase
344
360
  end
@@ -159,7 +159,7 @@
159
159
  # with it.
160
160
  #
161
161
  class CSV < Object
162
- include Enumerable[untyped, untyped]
162
+ include Enumerable[untyped]
163
163
 
164
164
  # This method is intended as the primary interface for reading CSV files. You
165
165
  # pass a `path` and any `options` you wish to set for the read. Each row of file
@@ -407,7 +407,7 @@ CSV::VERSION: String
407
407
  # processing is activated.
408
408
  #
409
409
  class CSV::Row < Object
410
- include Enumerable[untyped, untyped]
410
+ include Enumerable[untyped]
411
411
 
412
412
  # If a two-element Array is provided, it is assumed to be a header and field and
413
413
  # the pair is appended. A Hash works the same way with the key being the header
@@ -578,7 +578,7 @@ end
578
578
  # processing is activated.
579
579
  #
580
580
  class CSV::Table[out Elem] < Object
581
- include Enumerable[untyped, untyped]
581
+ include Enumerable[untyped]
582
582
 
583
583
  # Constructs a new CSV::Table from `array_of_rows`, which are expected to be
584
584
  # CSV::Row objects. All rows are assumed to have the same headers.
@@ -61,7 +61,7 @@
61
61
  # puts db['822']
62
62
  #
63
63
  class DBM
64
- include Enumerable[untyped, untyped]
64
+ include Enumerable[untyped]
65
65
 
66
66
  # Open a dbm database and yields it if a block is given. See also `DBM.new`.
67
67
  #
@@ -138,8 +138,6 @@ class DBM
138
138
  #
139
139
  def include?: (String) -> bool
140
140
 
141
- def index: (untyped) -> (String | NilClass)
142
-
143
141
  # Returns a Hash (not a DBM database) created by using each value in the
144
142
  # database as a key, with the corresponding key as its value.
145
143
  #
@@ -0,0 +1,119 @@
1
+ # Use the Monitor class when you want to have a lock object for blocks with
2
+ # mutual exclusion.
3
+ #
4
+ # require 'monitor'
5
+ #
6
+ # lock = Monitor.new
7
+ # lock.synchronize do
8
+ # # exclusive access
9
+ # end
10
+ class Monitor
11
+ public
12
+
13
+ def enter: () -> nil
14
+
15
+ def exit: () -> nil
16
+
17
+ def mon_check_owner: () -> nil
18
+
19
+ alias mon_enter enter
20
+
21
+ alias mon_exit exit
22
+
23
+ def mon_locked?: () -> bool
24
+
25
+ def mon_owned?: () -> bool
26
+
27
+ alias mon_synchronize synchronize
28
+
29
+ alias mon_try_enter try_enter
30
+
31
+ def new_cond: () -> ::MonitorMixin::ConditionVariable
32
+
33
+ def synchronize: [T] () { () -> T } -> T
34
+
35
+ def try_enter: () -> bool
36
+
37
+ # for compatibility
38
+ alias try_mon_enter try_enter
39
+
40
+ def wait_for_cond: (::MonitorMixin::ConditionVariable, Numeric? timeout) -> untyped
41
+ end
42
+
43
+ module MonitorMixin
44
+ def self.extend_object: (untyped obj) -> untyped
45
+
46
+ public
47
+
48
+ # Enters exclusive section.
49
+ def mon_enter: () -> nil
50
+
51
+ # Leaves exclusive section.
52
+ def mon_exit: () -> nil
53
+
54
+ # Returns true if this monitor is locked by any thread
55
+ def mon_locked?: () -> bool
56
+
57
+ # Returns true if this monitor is locked by current thread.
58
+ def mon_owned?: () -> bool
59
+
60
+ # Enters exclusive section and executes the block. Leaves the exclusive section
61
+ # automatically when the block exits. See example under `MonitorMixin`.
62
+ def mon_synchronize: [T] () { () -> T } -> T
63
+
64
+ # Attempts to enter exclusive section. Returns `false` if lock fails.
65
+ def mon_try_enter: () -> bool
66
+
67
+ # Creates a new MonitorMixin::ConditionVariable associated with the Monitor
68
+ # object.
69
+ def new_cond: () -> ::MonitorMixin::ConditionVariable
70
+
71
+ alias synchronize mon_synchronize
72
+
73
+ # For backward compatibility
74
+ alias try_mon_enter mon_try_enter
75
+
76
+ private
77
+
78
+ # Use `extend MonitorMixin` or `include MonitorMixin` instead of this
79
+ # constructor. Have look at the examples above to understand how to use this
80
+ # module.
81
+ def initialize: (*untyped) { (*untyped) -> untyped } -> void
82
+
83
+ def mon_check_owner: () -> nil
84
+
85
+ # Initializes the MonitorMixin after being included in a class or when an object
86
+ # has been extended with the MonitorMixin
87
+ def mon_initialize: () -> untyped
88
+ end
89
+
90
+ # FIXME: This isn't documented in Nutshell.
91
+ #
92
+ # Since MonitorMixin.new_cond returns a ConditionVariable, and the example above
93
+ # calls while_wait and signal, this class should be documented.
94
+ class MonitorMixin::ConditionVariable
95
+ public
96
+
97
+ # Wakes up all threads waiting for this lock.
98
+ def broadcast: () -> Thread::ConditionVariable
99
+
100
+ # Wakes up the first thread in line waiting for this lock.
101
+ def signal: () -> Thread::ConditionVariable
102
+
103
+ # Releases the lock held in the associated monitor and waits; reacquires the
104
+ # lock on wakeup.
105
+ #
106
+ # If `timeout` is given, this method returns after `timeout` seconds passed,
107
+ # even if no other thread doesn't signal.
108
+ def wait: (?Numeric? timeout) -> untyped
109
+
110
+ # Calls wait repeatedly until the given block yields a truthy value.
111
+ def wait_until: () { () -> boolish } -> untyped
112
+
113
+ # Calls wait repeatedly while the given block yields a truthy value.
114
+ def wait_while: () { () -> boolish } -> untyped
115
+
116
+ private
117
+
118
+ def initialize: (Monitor monitor) -> void
119
+ end
@@ -137,7 +137,7 @@ class Prime
137
137
  class PseudoPrimeGenerator
138
138
  def initialize: (?Integer?) -> void
139
139
 
140
- include Enumerable[Integer, void]
140
+ include Enumerable[Integer]
141
141
 
142
142
  attr_accessor upper_bound (): Integer?
143
143
 
@@ -51,8 +51,8 @@ class Set[A]
51
51
  # Set.new(1..5) #=> #<Set: {1, 2, 3, 4, 5}>
52
52
  # Set.new([1, 2, 3]) { |x| x * x } #=> #<Set: {1, 4, 9}>
53
53
  #
54
- def initialize: (_Each[A, untyped]) -> untyped
55
- | [X] (_Each[X, untyped]) { (X) -> A } -> untyped
54
+ def initialize: (_Each[A]) -> untyped
55
+ | [X] (_Each[X]) { (X) -> A } -> untyped
56
56
  | (?nil) -> untyped
57
57
 
58
58
  # Creates a new set containing the given objects.
@@ -69,7 +69,7 @@ class Set[A]
69
69
  # Set[1, 3, 5] & Set[3, 2, 1] #=> #<Set: {3, 1}>
70
70
  # Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> #<Set: {"a", "b"}>
71
71
  #
72
- def &: (_Each[A, untyped]) -> self
72
+ def &: (_Each[A]) -> self
73
73
 
74
74
  alias intersection &
75
75
 
@@ -79,7 +79,7 @@ class Set[A]
79
79
  # Set[1, 2, 3] | Set[2, 4, 5] #=> #<Set: {1, 2, 3, 4, 5}>
80
80
  # Set[1, 5, 'z'] | (1..6) #=> #<Set: {1, 5, "z", 2, 3, 4, 6}>
81
81
  #
82
- def |: (_Each[A, untyped]) -> self
82
+ def |: (_Each[A]) -> self
83
83
 
84
84
  alias union |
85
85
 
@@ -91,7 +91,7 @@ class Set[A]
91
91
  # Set[1, 3, 5] - Set[1, 5] #=> #<Set: {3}>
92
92
  # Set['a', 'b', 'z'] - ['a', 'c'] #=> #<Set: {"b", "z"}>
93
93
  #
94
- def -: (_Each[A, untyped]) -> self
94
+ def -: (_Each[A]) -> self
95
95
 
96
96
  alias difference -
97
97
 
@@ -133,7 +133,7 @@ class Set[A]
133
133
  # Set[1, 2] ^ Set[2, 3] #=> #<Set: {3, 1}>
134
134
  # Set[1, 'b', 'c'] ^ ['b', 'd'] #=> #<Set: {"d", 1, "c"}>
135
135
  #
136
- def ^: (_Each[A, untyped]) -> self
136
+ def ^: (_Each[A]) -> self
137
137
 
138
138
  # Classifies the set by the return value of the given block and returns a hash
139
139
  # of {value => set of elements} pairs. The block is called once for each
@@ -248,7 +248,7 @@ class Set[A]
248
248
  # Merges the elements of the given enumerable object to the set and returns
249
249
  # self.
250
250
  #
251
- def merge: (_Each[A, untyped]) -> self
251
+ def merge: (_Each[A]) -> self
252
252
 
253
253
  # Returns true if the set is a subset of the given set.
254
254
  #
@@ -271,7 +271,7 @@ class Set[A]
271
271
  # set.replace([1, 2]) #=> #<Set: {1, 2}>
272
272
  # set #=> #<Set: {1, 2}>
273
273
  #
274
- def replace: (_Each[A, untyped]) -> self
274
+ def replace: (_Each[A]) -> self
275
275
 
276
276
  # Resets the internal state after modification to existing elements and returns
277
277
  # self.
@@ -288,7 +288,7 @@ class Set[A]
288
288
  # Deletes every element that appears in the given enumerable object and returns
289
289
  # self.
290
290
  #
291
- def subtract: (_Each[A, untyped]) -> self
291
+ def subtract: (_Each[A]) -> self
292
292
 
293
293
  # Converts the set to an array. The order of elements is uncertain.
294
294
  #
@@ -297,5 +297,5 @@ class Set[A]
297
297
  #
298
298
  def to_a: () -> Array[A]
299
299
 
300
- include Enumerable[A, self]
300
+ include Enumerable[A]
301
301
  end
@@ -0,0 +1,111 @@
1
+ # The Singleton module implements the Singleton pattern.
2
+ #
3
+ # ## Usage
4
+ #
5
+ # To use Singleton, include the module in your class.
6
+ #
7
+ # class Klass
8
+ # include Singleton
9
+ # # ...
10
+ # end
11
+ #
12
+ # This ensures that only one instance of Klass can be created.
13
+ #
14
+ # a,b = Klass.instance, Klass.instance
15
+ #
16
+ # a == b
17
+ # # => true
18
+ #
19
+ # Klass.new
20
+ # # => NoMethodError - new is private ...
21
+ #
22
+ # The instance is created at upon the first call of Klass.instance().
23
+ #
24
+ # class OtherKlass
25
+ # include Singleton
26
+ # # ...
27
+ # end
28
+ #
29
+ # ObjectSpace.each_object(OtherKlass){}
30
+ # # => 0
31
+ #
32
+ # OtherKlass.instance
33
+ # ObjectSpace.each_object(OtherKlass){}
34
+ # # => 1
35
+ #
36
+ # This behavior is preserved under inheritance and cloning.
37
+ #
38
+ # ## Implementation
39
+ #
40
+ # This above is achieved by:
41
+ #
42
+ # * Making Klass.new and Klass.allocate private.
43
+ #
44
+ # * Overriding Klass.inherited(sub_klass) and Klass.clone() to ensure that the
45
+ # Singleton properties are kept when inherited and cloned.
46
+ #
47
+ # * Providing the Klass.instance() method that returns the same object each
48
+ # time it is called.
49
+ #
50
+ # * Overriding Klass._load(str) to call Klass.instance().
51
+ #
52
+ # * Overriding Klass#clone and Klass#dup to raise TypeErrors to prevent
53
+ # cloning or duping.
54
+ #
55
+ #
56
+ # ## Singleton and Marshal
57
+ #
58
+ # By default Singleton's #_dump(depth) returns the empty string. Marshalling by
59
+ # default will strip state information, e.g. instance variables from the
60
+ # instance. Classes using Singleton can provide custom _load(str) and
61
+ # _dump(depth) methods to retain some of the previous state of the instance.
62
+ #
63
+ # require 'singleton'
64
+ #
65
+ # class Example
66
+ # include Singleton
67
+ # attr_accessor :keep, :strip
68
+ # def _dump(depth)
69
+ # # this strips the @strip information from the instance
70
+ # Marshal.dump(@keep, depth)
71
+ # end
72
+ #
73
+ # def self._load(str)
74
+ # instance.keep = Marshal.load(str)
75
+ # instance
76
+ # end
77
+ # end
78
+ #
79
+ # a = Example.instance
80
+ # a.keep = "keep this"
81
+ # a.strip = "get rid of this"
82
+ #
83
+ # stored_state = Marshal.dump(a)
84
+ #
85
+ # a.keep = nil
86
+ # a.strip = nil
87
+ # b = Marshal.load(stored_state)
88
+ # p a == b # => true
89
+ # p a.keep # => "keep this"
90
+ # p a.strip # => nil
91
+ module Singleton
92
+ def self.__init__: (Class klass) -> Class
93
+
94
+ def self.instance: () -> instance
95
+
96
+ public
97
+
98
+ # By default, do not retain any state when marshalling.
99
+ #
100
+ def _dump: (?Integer depth) -> String
101
+
102
+ # Raises a TypeError to prevent cloning.
103
+ #
104
+ def clone: () -> bot
105
+
106
+ # Raises a TypeError to prevent duping.
107
+ #
108
+ def dup: () -> bot
109
+ end
110
+
111
+ Singleton::VERSION: String
@@ -0,0 +1,4 @@
1
+ module TSort[Node]
2
+ class Cyclic < StandardError
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ module TSort[Node]
2
+ interface _Sortable[Node]
3
+ # #tsort_each_node is used to iterate for all nodes over a graph.
4
+ #
5
+ def tsort_each_node: () { (Node) -> void } -> void
6
+
7
+ # #tsort_each_child is used to iterate for child nodes of node.
8
+ #
9
+ def tsort_each_child: (Node) { (Node) -> void } -> void
10
+ end
11
+
12
+ interface _EachNode[Node]
13
+ def call: () { (Node) -> void } -> void
14
+ end
15
+
16
+ interface _EachChild[Node]
17
+ def call: (Node) { (Node) -> void } -> void
18
+ end
19
+ end
@@ -0,0 +1,371 @@
1
+ # TSort implements topological sorting using Tarjan's algorithm for strongly
2
+ # connected components.
3
+ #
4
+ # TSort is designed to be able to be used with any object which can be
5
+ # interpreted as a directed graph.
6
+ #
7
+ # TSort requires two methods to interpret an object as a graph, tsort_each_node
8
+ # and tsort_each_child.
9
+ #
10
+ # * tsort_each_node is used to iterate for all nodes over a graph.
11
+ # * tsort_each_child is used to iterate for child nodes of a given node.
12
+ #
13
+ #
14
+ # The equality of nodes are defined by eql? and hash since TSort uses Hash
15
+ # internally.
16
+ #
17
+ # ## A Simple Example
18
+ #
19
+ # The following example demonstrates how to mix the TSort module into an
20
+ # existing class (in this case, Hash). Here, we're treating each key in the hash
21
+ # as a node in the graph, and so we simply alias the required #tsort_each_node
22
+ # method to Hash's #each_key method. For each key in the hash, the associated
23
+ # value is an array of the node's child nodes. This choice in turn leads to our
24
+ # implementation of the required #tsort_each_child method, which fetches the
25
+ # array of child nodes and then iterates over that array using the user-supplied
26
+ # block.
27
+ #
28
+ # require 'tsort'
29
+ #
30
+ # class Hash
31
+ # include TSort
32
+ # alias tsort_each_node each_key
33
+ # def tsort_each_child(node, &block)
34
+ # fetch(node).each(&block)
35
+ # end
36
+ # end
37
+ #
38
+ # {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
39
+ # #=> [3, 2, 1, 4]
40
+ #
41
+ # {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
42
+ # #=> [[4], [2, 3], [1]]
43
+ #
44
+ # ## A More Realistic Example
45
+ #
46
+ # A very simple `make' like tool can be implemented as follows:
47
+ #
48
+ # require 'tsort'
49
+ #
50
+ # class Make
51
+ # def initialize
52
+ # @dep = {}
53
+ # @dep.default = []
54
+ # end
55
+ #
56
+ # def rule(outputs, inputs=[], &block)
57
+ # triple = [outputs, inputs, block]
58
+ # outputs.each {|f| @dep[f] = [triple]}
59
+ # @dep[triple] = inputs
60
+ # end
61
+ #
62
+ # def build(target)
63
+ # each_strongly_connected_component_from(target) {|ns|
64
+ # if ns.length != 1
65
+ # fs = ns.delete_if {|n| Array === n}
66
+ # raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
67
+ # end
68
+ # n = ns.first
69
+ # if Array === n
70
+ # outputs, inputs, block = n
71
+ # inputs_time = inputs.map {|f| File.mtime f}.max
72
+ # begin
73
+ # outputs_time = outputs.map {|f| File.mtime f}.min
74
+ # rescue Errno::ENOENT
75
+ # outputs_time = nil
76
+ # end
77
+ # if outputs_time == nil ||
78
+ # inputs_time != nil && outputs_time <= inputs_time
79
+ # sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i
80
+ # block.call
81
+ # end
82
+ # end
83
+ # }
84
+ # end
85
+ #
86
+ # def tsort_each_child(node, &block)
87
+ # @dep[node].each(&block)
88
+ # end
89
+ # include TSort
90
+ # end
91
+ #
92
+ # def command(arg)
93
+ # print arg, "\n"
94
+ # system arg
95
+ # end
96
+ #
97
+ # m = Make.new
98
+ # m.rule(%w[t1]) { command 'date > t1' }
99
+ # m.rule(%w[t2]) { command 'date > t2' }
100
+ # m.rule(%w[t3]) { command 'date > t3' }
101
+ # m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' }
102
+ # m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' }
103
+ # m.build('t5')
104
+ #
105
+ # ## Bugs
106
+ #
107
+ # * 'tsort.rb' is wrong name because this library uses Tarjan's algorithm for
108
+ # strongly connected components. Although 'strongly_connected_components.rb'
109
+ # is correct but too long.
110
+ #
111
+ #
112
+ # ## References
113
+ #
114
+ # 1. Tarjan, "Depth First Search and Linear Graph Algorithms",
115
+ #
116
+ #
117
+ # *SIAM Journal on Computing*, Vol. 1, No. 2, pp. 146-160, June 1972.
118
+ module TSort[Node] : TSort::_Sortable[Node]
119
+ # The iterator version of the TSort.strongly_connected_components method.
120
+ #
121
+ # The graph is represented by *each_node* and *each_child*. *each_node* should
122
+ # have `call` method which yields for each node in the graph. *each_child*
123
+ # should have `call` method which takes a node argument and yields for each
124
+ # child node.
125
+ #
126
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
127
+ # each_node = lambda {|&b| g.each_key(&b) }
128
+ # each_child = lambda {|n, &b| g[n].each(&b) }
129
+ # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
130
+ # #=> [4]
131
+ # # [2]
132
+ # # [3]
133
+ # # [1]
134
+ #
135
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
136
+ # each_node = lambda {|&b| g.each_key(&b) }
137
+ # each_child = lambda {|n, &b| g[n].each(&b) }
138
+ # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
139
+ # #=> [4]
140
+ # # [2, 3]
141
+ # # [1]
142
+ #
143
+ def self.each_strongly_connected_component: [T] (_EachNode[T] each_node, _EachChild[T] each_child) { (Array[T]) -> void } -> void
144
+ | [T] (_EachNode[T] each_node, _EachChild[T] each_child) -> Enumerator[Array[T], void]
145
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) { (Array[T]) -> void } -> void
146
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) -> Enumerator[Array[T], void]
147
+
148
+ # Iterates over strongly connected components in a graph. The graph is
149
+ # represented by *node* and *each_child*.
150
+ #
151
+ # *node* is the first node. *each_child* should have `call` method which takes a
152
+ # node argument and yields for each child node.
153
+ #
154
+ # Return value is unspecified.
155
+ #
156
+ # #TSort.each_strongly_connected_component_from is a class method and it doesn't
157
+ # need a class to represent a graph which includes TSort.
158
+ #
159
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
160
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
161
+ # TSort.each_strongly_connected_component_from(1, each_child) {|scc|
162
+ # p scc
163
+ # }
164
+ # #=> [4]
165
+ # # [2, 3]
166
+ # # [1]
167
+ #
168
+ def self.each_strongly_connected_component_from: [T] (T node, _EachChild[T] each_child, ?untyped id_map, ?untyped stack) { (Array[T]) -> void } -> void
169
+ | [T] (T node, _EachChild[T] each_child, ?untyped id_map, ?untyped stack) -> Enumerator[Array[T], void]
170
+ | [T] (T node, ^(T) { (T) -> void } -> void each_child, ?untyped id_map, ?untyped stack) { (Array[T]) -> void } -> void
171
+ | [T] (T node, ^(T) { (T) -> void } -> void each_child, ?untyped id_map, ?untyped stack) -> Enumerator[Array[T], void]
172
+
173
+ # Returns strongly connected components as an array of arrays of nodes. The
174
+ # array is sorted from children to parents. Each elements of the array
175
+ # represents a strongly connected component.
176
+ #
177
+ # The graph is represented by *each_node* and *each_child*. *each_node* should
178
+ # have `call` method which yields for each node in the graph. *each_child*
179
+ # should have `call` method which takes a node argument and yields for each
180
+ # child node.
181
+ #
182
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
183
+ # each_node = lambda {|&b| g.each_key(&b) }
184
+ # each_child = lambda {|n, &b| g[n].each(&b) }
185
+ # p TSort.strongly_connected_components(each_node, each_child)
186
+ # #=> [[4], [2], [3], [1]]
187
+ #
188
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
189
+ # each_node = lambda {|&b| g.each_key(&b) }
190
+ # each_child = lambda {|n, &b| g[n].each(&b) }
191
+ # p TSort.strongly_connected_components(each_node, each_child)
192
+ # #=> [[4], [2, 3], [1]]
193
+ #
194
+ def self.strongly_connected_components: [T] (_EachNode[T] each_node, _EachChild[T] each_child) -> Array[Array[T]]
195
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) -> Array[Array[T]]
196
+
197
+ # Returns a topologically sorted array of nodes. The array is sorted from
198
+ # children to parents, i.e. the first element has no child and the last node has
199
+ # no parent.
200
+ #
201
+ # The graph is represented by *each_node* and *each_child*. *each_node* should
202
+ # have `call` method which yields for each node in the graph. *each_child*
203
+ # should have `call` method which takes a node argument and yields for each
204
+ # child node.
205
+ #
206
+ # If there is a cycle, TSort::Cyclic is raised.
207
+ #
208
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
209
+ # each_node = lambda {|&b| g.each_key(&b) }
210
+ # each_child = lambda {|n, &b| g[n].each(&b) }
211
+ # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
212
+ #
213
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
214
+ # each_node = lambda {|&b| g.each_key(&b) }
215
+ # each_child = lambda {|n, &b| g[n].each(&b) }
216
+ # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic
217
+ #
218
+ def self.tsort: [T] (_EachNode[T] each_node, _EachChild[T] each_child) -> Array[T]
219
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) -> Array[T]
220
+
221
+ # The iterator version of the TSort.tsort method.
222
+ #
223
+ # The graph is represented by *each_node* and *each_child*. *each_node* should
224
+ # have `call` method which yields for each node in the graph. *each_child*
225
+ # should have `call` method which takes a node argument and yields for each
226
+ # child node.
227
+ #
228
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
229
+ # each_node = lambda {|&b| g.each_key(&b) }
230
+ # each_child = lambda {|n, &b| g[n].each(&b) }
231
+ # TSort.tsort_each(each_node, each_child) {|n| p n }
232
+ # #=> 4
233
+ # # 2
234
+ # # 3
235
+ # # 1
236
+ #
237
+ def self.tsort_each: [T] (_EachNode[T] each_node, _EachChild[T] each_child) { (T) -> void } -> void
238
+ | [T] (_EachNode[T] each_node, _EachChild[T] each_child) -> Enumerator[T, void]
239
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) { (T) -> void } -> void
240
+ | [T] (^() { (T) -> void } -> void each_node, ^(T) { (T) -> void } -> void each_child) -> Enumerator[T, void]
241
+
242
+ # The iterator version of the #strongly_connected_components method.
243
+ # *`obj*.each_strongly_connected_component` is similar to
244
+ # *`obj*.strongly_connected_components.each`, but modification of *obj* during
245
+ # the iteration may lead to unexpected results.
246
+ #
247
+ # #each_strongly_connected_component returns `nil`.
248
+ #
249
+ # class G
250
+ # include TSort
251
+ # def initialize(g)
252
+ # @g = g
253
+ # end
254
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
255
+ # def tsort_each_node(&b) @g.each_key(&b) end
256
+ # end
257
+ #
258
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
259
+ # graph.each_strongly_connected_component {|scc| p scc }
260
+ # #=> [4]
261
+ # # [2]
262
+ # # [3]
263
+ # # [1]
264
+ #
265
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
266
+ # graph.each_strongly_connected_component {|scc| p scc }
267
+ # #=> [4]
268
+ # # [2, 3]
269
+ # # [1]
270
+ #
271
+ def each_strongly_connected_component: () { (Array[Node]) -> void } -> void
272
+ | () -> Enumerator[Array[Node], void]
273
+
274
+ # Iterates over strongly connected component in the subgraph reachable from
275
+ # *node*.
276
+ #
277
+ # Return value is unspecified.
278
+ #
279
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
280
+ #
281
+ # class G
282
+ # include TSort
283
+ # def initialize(g)
284
+ # @g = g
285
+ # end
286
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
287
+ # def tsort_each_node(&b) @g.each_key(&b) end
288
+ # end
289
+ #
290
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
291
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
292
+ # #=> [4]
293
+ # # [2]
294
+ #
295
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
296
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
297
+ # #=> [4]
298
+ # # [2, 3]
299
+ #
300
+ def each_strongly_connected_component_from: (Node, ?untyped id_map, ?untyped stack) { (Array[Node]) -> void } -> void
301
+ | (Node, ?untyped id_map, ?untyped stack) -> Enumerator[Array[Node], void]
302
+
303
+ # Returns strongly connected components as an array of arrays of nodes. The
304
+ # array is sorted from children to parents. Each elements of the array
305
+ # represents a strongly connected component.
306
+ #
307
+ # class G
308
+ # include TSort
309
+ # def initialize(g)
310
+ # @g = g
311
+ # end
312
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
313
+ # def tsort_each_node(&b) @g.each_key(&b) end
314
+ # end
315
+ #
316
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
317
+ # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
318
+ #
319
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
320
+ # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
321
+ #
322
+ def strongly_connected_components: () -> Array[Array[Node]]
323
+
324
+ # Returns a topologically sorted array of nodes. The array is sorted from
325
+ # children to parents, i.e. the first element has no child and the last node has
326
+ # no parent.
327
+ #
328
+ # If there is a cycle, TSort::Cyclic is raised.
329
+ #
330
+ # class G
331
+ # include TSort
332
+ # def initialize(g)
333
+ # @g = g
334
+ # end
335
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
336
+ # def tsort_each_node(&b) @g.each_key(&b) end
337
+ # end
338
+ #
339
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
340
+ # p graph.tsort #=> [4, 2, 3, 1]
341
+ #
342
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
343
+ # p graph.tsort # raises TSort::Cyclic
344
+ #
345
+ def tsort: () -> Array[Node]
346
+
347
+ # The iterator version of the #tsort method. *`obj*.tsort_each` is similar to
348
+ # *`obj*.tsort.each`, but modification of *obj* during the iteration may lead to
349
+ # unexpected results.
350
+ #
351
+ # #tsort_each returns `nil`. If there is a cycle, TSort::Cyclic is raised.
352
+ #
353
+ # class G
354
+ # include TSort
355
+ # def initialize(g)
356
+ # @g = g
357
+ # end
358
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
359
+ # def tsort_each_node(&b) @g.each_key(&b) end
360
+ # end
361
+ #
362
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
363
+ # graph.tsort_each {|n| p n }
364
+ # #=> 4
365
+ # # 2
366
+ # # 3
367
+ # # 1
368
+ #
369
+ def tsort_each: () { (Node) -> void } -> void
370
+ | () -> Enumerator[Node, void]
371
+ end