bcdd-result 0.9.0 → 0.10.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,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BCDD::Result
4
+ module Transitions
5
+ module Tracking
6
+ require_relative 'tracking/enabled'
7
+ require_relative 'tracking/disabled'
8
+
9
+ EMPTY_ARRAY = [].freeze
10
+ EMPTY_HASH = {}.freeze
11
+ EMPTY_TREE = Tree.new(nil).freeze
12
+ VERSION = 1
13
+ EMPTY = { version: VERSION, records: EMPTY_ARRAY, metadata: { duration: 0, tree_map: EMPTY_ARRAY } }.freeze
14
+
15
+ def self.instance
16
+ Config.instance.feature.enabled?(:transitions) ? Tracking::Enabled.new : Tracking::Disabled
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BCDD::Result
4
+ module Transitions
5
+ class Tree
6
+ class Node
7
+ attr_reader :id, :value, :parent, :normalizer, :children
8
+
9
+ def initialize(value, parent:, id:, normalizer:)
10
+ @normalizer = normalizer
11
+
12
+ @id = id
13
+ @value = normalizer.call(id, value)
14
+ @parent = parent
15
+
16
+ @children = []
17
+ end
18
+
19
+ def insert(value, id:)
20
+ node = self.class.new(value, parent: self, id: id, normalizer: normalizer)
21
+
22
+ @children << node
23
+
24
+ node
25
+ end
26
+
27
+ def root?
28
+ parent.nil?
29
+ end
30
+
31
+ def leaf?
32
+ children.empty?
33
+ end
34
+
35
+ def node?
36
+ !leaf?
37
+ end
38
+
39
+ def inspect
40
+ "#<#{self.class.name} id=#{id} children.size=#{children.size}>"
41
+ end
42
+ end
43
+
44
+ attr_reader :size, :root, :current
45
+
46
+ def initialize(value, normalizer: ->(_id, val) { val })
47
+ @size = 0
48
+
49
+ @root = Node.new(value, parent: nil, id: @size, normalizer: normalizer)
50
+
51
+ @current = @root
52
+ end
53
+
54
+ def root_value
55
+ root.value
56
+ end
57
+
58
+ def parent_value
59
+ current.parent&.value || root_value
60
+ end
61
+
62
+ def current_value
63
+ current.value
64
+ end
65
+
66
+ def insert(value)
67
+ @size += 1
68
+
69
+ current.insert(value, id: size)
70
+ end
71
+
72
+ def insert!(value)
73
+ @current = insert(value)
74
+ end
75
+
76
+ def move_up!(level = 1)
77
+ tap { level.times { @current = current.parent || root } }
78
+ end
79
+
80
+ def move_down!(level = 1, index: -1)
81
+ tap { level.times { current.children[index].then { |child| @current = child if child } } }
82
+ end
83
+
84
+ def move_to_root!
85
+ tap { @current = root }
86
+ end
87
+
88
+ NestedIds = ->(node) { [node.id, node.children.map(&NestedIds)] }
89
+
90
+ def nested_ids
91
+ NestedIds[root]
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BCDD::Result
4
+ module Transitions
5
+ require_relative 'transitions/tree'
6
+ require_relative 'transitions/tracking'
7
+
8
+ THREAD_VAR_NAME = :bcdd_result_transitions_tracking
9
+
10
+ def self.tracking
11
+ Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
12
+ end
13
+ end
14
+
15
+ def self.transitions(name: nil, desc: nil)
16
+ Transitions.tracking.start(name: name, desc: desc)
17
+
18
+ result = yield
19
+
20
+ result.is_a?(::BCDD::Result) or raise Error::UnexpectedOutcome.build(outcome: result, origin: :transitions)
21
+
22
+ Transitions.tracking.finish(result: result)
23
+
24
+ result
25
+ rescue ::Exception => e
26
+ Transitions.tracking.reset!
27
+
28
+ raise e
29
+ end
30
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BCDD
4
4
  class Result
5
- VERSION = '0.9.0'
5
+ VERSION = '0.10.0'
6
6
  end
7
7
  end
data/lib/bcdd/result.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'result/version'
4
+ require_relative 'result/transitions'
4
5
  require_relative 'result/error'
5
6
  require_relative 'result/data'
6
7
  require_relative 'result/handler'
@@ -13,13 +14,13 @@ require_relative 'result/context'
13
14
  require_relative 'result/config'
14
15
 
15
16
  class BCDD::Result
16
- attr_accessor :unknown
17
+ attr_accessor :unknown, :transitions
17
18
 
18
19
  attr_reader :subject, :data, :type_checker, :halted
19
20
 
20
21
  protected :subject
21
22
 
22
- private :unknown, :unknown=, :type_checker
23
+ private :unknown, :unknown=, :type_checker, :transitions=
23
24
 
24
25
  def self.config
25
26
  Config.instance
@@ -40,6 +41,9 @@ class BCDD::Result
40
41
  @data = data
41
42
 
42
43
  self.unknown = true
44
+ self.transitions = Transitions::Tracking::EMPTY
45
+
46
+ Transitions.tracking.record(self)
43
47
  end
44
48
 
45
49
  def halted?
@@ -84,16 +88,12 @@ class BCDD::Result
84
88
  tap { yield(value, type) if unknown }
85
89
  end
86
90
 
87
- def and_then(method_name = nil, context = nil)
91
+ def and_then(method_name = nil, context = nil, &block)
88
92
  return self if halted?
89
93
 
90
- method_name && block_given? and raise ::ArgumentError, 'method_name and block are mutually exclusive'
91
-
92
- return call_subject_method(method_name, context) if method_name
93
-
94
- result = yield(value)
94
+ method_name && block and raise ::ArgumentError, 'method_name and block are mutually exclusive'
95
95
 
96
- ensure_result_object(result, origin: :block)
96
+ method_name ? call_and_then_subject_method(method_name, context) : call_and_then_block(block)
97
97
  end
98
98
 
99
99
  def handle
@@ -139,18 +139,35 @@ class BCDD::Result
139
139
  block.call(value, type)
140
140
  end
141
141
 
142
- def call_subject_method(method_name, context)
142
+ def call_and_then_subject_method(method_name, context_data)
143
143
  method = subject.method(method_name)
144
144
 
145
- result =
146
- case method.arity
147
- when 0 then subject.send(method_name)
148
- when 1 then subject.send(method_name, value)
149
- when 2 then subject.send(method_name, value, context)
150
- else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 2)
151
- end
145
+ Transitions.tracking.record_and_then(method, context_data, subject) do
146
+ result = call_and_then_subject_method!(method, context_data)
147
+
148
+ ensure_result_object(result, origin: :method)
149
+ end
150
+ end
151
+
152
+ def call_and_then_subject_method!(method, context_data)
153
+ case method.arity
154
+ when 0 then subject.send(method.name)
155
+ when 1 then subject.send(method.name, value)
156
+ when 2 then subject.send(method.name, value, context_data)
157
+ else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 2)
158
+ end
159
+ end
160
+
161
+ def call_and_then_block(block)
162
+ Transitions.tracking.record_and_then(:block, nil, subject) do
163
+ result = call_and_then_block!(block)
164
+
165
+ ensure_result_object(result, origin: :block)
166
+ end
167
+ end
152
168
 
153
- ensure_result_object(result, origin: :method)
169
+ def call_and_then_block!(block)
170
+ block.call(value)
154
171
  end
155
172
 
156
173
  def ensure_result_object(result, origin:)
@@ -0,0 +1,100 @@
1
+ class BCDD::Result::Config
2
+ include Singleton
3
+
4
+ ADDON: Hash[Symbol, Hash[Symbol, untyped]]
5
+ FEATURE: Hash[Symbol, Hash[Symbol, untyped]]
6
+ PATTERN_MATCHING: Hash[Symbol, Hash[Symbol, untyped]]
7
+
8
+ attr_reader addon: BCDD::Result::Config::Switcher
9
+ attr_reader feature: BCDD::Result::Config::Switcher
10
+ attr_reader constant_alias: BCDD::Result::Config::Switcher
11
+ attr_reader pattern_matching: BCDD::Result::Config::Switcher
12
+
13
+ def self.instance: -> BCDD::Result::Config
14
+
15
+ def initialize: -> void
16
+
17
+ def freeze: -> BCDD::Result::Config
18
+ def options: -> Hash[Symbol, BCDD::Result::Config::Switcher]
19
+ def to_h: -> Hash[Symbol, Hash[Symbol | String, bool]]
20
+ end
21
+
22
+ module BCDD::Result::Config::Options
23
+ def self.with_defaults: (
24
+ Hash[Symbol, Hash[Symbol, bool]],
25
+ Symbol
26
+ ) -> Hash[Symbol, bool]
27
+
28
+ def self.select: (
29
+ Hash[Symbol, Hash[Symbol, bool]],
30
+ config: Symbol,
31
+ from: Hash[Symbol, untyped]
32
+ ) -> Hash[Symbol, untyped]
33
+
34
+ def self.addon: (
35
+ map: Hash[Symbol, Hash[Symbol, bool]],
36
+ from: Hash[Symbol, Module]
37
+ ) -> Hash[Symbol, Module]
38
+ end
39
+
40
+ class BCDD::Result::Config::Switcher
41
+ private attr_reader _affects: Hash[Symbol | String, Array[String]]
42
+ private attr_reader _options: Hash[Symbol | String, bool]
43
+ private attr_reader listener: Proc
44
+
45
+ def initialize: (
46
+ options: Hash[Symbol | String, Hash[Symbol, untyped]],
47
+ ?listener: Proc
48
+ ) -> void
49
+
50
+ def freeze: -> BCDD::Result::Config::Switcher
51
+
52
+ def to_h: -> Hash[Symbol | String, bool]
53
+
54
+ def options: -> Hash[Symbol | String, Hash[Symbol, untyped]]
55
+
56
+ def enabled?: (Symbol | String) -> bool
57
+
58
+ def enable!: (*(Symbol | String)) -> Hash[Symbol | String, Hash[Symbol, untyped]]
59
+
60
+ def disable!: (*(Symbol | String)) -> Hash[Symbol | String, Hash[Symbol, untyped]]
61
+
62
+ private
63
+
64
+ def set_many: (Array[Symbol | String], to: bool) -> Hash[Symbol | String, Hash[Symbol, untyped]]
65
+
66
+ def set_one: (Symbol | String, bool) -> void
67
+
68
+ def require_option!: (Array[Symbol | String]) -> void
69
+
70
+ def validate_option!: (Symbol | String) -> void
71
+
72
+ def available_options_message: -> String
73
+ end
74
+
75
+ module BCDD::Result::Config::Addons
76
+ OPTIONS: Hash[String, Hash[Symbol, untyped]]
77
+
78
+ def self.switcher: -> BCDD::Result::Config::Switcher
79
+ end
80
+
81
+ module BCDD::Result::Config::ConstantAliases
82
+ MAPPING: Hash[String, Hash[Symbol, untyped]]
83
+ OPTIONS: Hash[String, Hash[Symbol, untyped]]
84
+ Listener: Proc
85
+
86
+ def self.switcher: -> BCDD::Result::Config::Switcher
87
+ end
88
+
89
+ module BCDD::Result::Config::Features
90
+ OPTIONS: Hash[String, Hash[Symbol, untyped]]
91
+ Listener: Proc
92
+
93
+ def self.switcher: -> BCDD::Result::Config::Switcher
94
+ end
95
+
96
+ module BCDD::Result::Config::PatternMatching
97
+ OPTIONS: Hash[String, Hash[Symbol, untyped]]
98
+
99
+ def self.switcher: -> BCDD::Result::Config::Switcher
100
+ end
@@ -0,0 +1,102 @@
1
+ class BCDD::Result::Context < BCDD::Result
2
+ EXPECTED_OUTCOME: String
3
+
4
+ SubjectMethodArity: ^(Method) -> Integer
5
+
6
+ attr_reader acc: Hash[Symbol, untyped]
7
+
8
+ def initialize: (
9
+ type: Symbol,
10
+ value: untyped,
11
+ ?subject: untyped,
12
+ ?expectations: BCDD::Result::Contract::Evaluator,
13
+ ?halted: bool
14
+ ) -> void
15
+
16
+ def and_then: (?Symbol, **untyped) ?{ (Hash[Symbol, untyped]) -> untyped } -> BCDD::Result::Context
17
+
18
+ private
19
+
20
+ def call_and_then_subject_method: (Symbol, Hash[Symbol, untyped]) -> BCDD::Result::Context
21
+ def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result::Context
22
+
23
+ def raise_unexpected_outcome_error: (BCDD::Result::Context | untyped, Symbol) -> void
24
+ end
25
+
26
+ class BCDD::Result::Context
27
+ class Success < BCDD::Result::Context
28
+ include BCDD::Result::Success::Methods
29
+
30
+ def and_expose: (Symbol, Array[Symbol], halted: bool) -> BCDD::Result::Context::Success
31
+ end
32
+
33
+ def self.Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
34
+ end
35
+
36
+ class BCDD::Result::Context
37
+ class Failure < BCDD::Result::Context
38
+ include BCDD::Result::Failure::Methods
39
+
40
+ def and_expose: (Symbol, Array[Symbol], **untyped) -> BCDD::Result::Context::Failure
41
+ end
42
+
43
+ def self.Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
44
+ end
45
+
46
+ class BCDD::Result::Context
47
+ module Mixin
48
+ Factory: singleton(BCDD::Result::Mixin::Factory)
49
+
50
+ module Methods
51
+ def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
52
+
53
+ def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
54
+
55
+ private
56
+
57
+ def _ResultAs: (singleton(BCDD::Result::Context), Symbol, untyped, ?halted: bool) -> untyped
58
+ end
59
+
60
+ module Addons
61
+ module Continuable
62
+ include BCDD::Result::Context::Mixin::Methods
63
+
64
+ private
65
+
66
+ def Continue: (**untyped) -> BCDD::Result::Context::Success
67
+ end
68
+
69
+ OPTIONS: Hash[Symbol, Module]
70
+
71
+ def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
72
+ end
73
+ end
74
+
75
+ def self.mixin_module: -> singleton(BCDD::Result::Context::Mixin)
76
+
77
+ def self.result_factory: -> singleton(BCDD::Result::Context)
78
+ end
79
+
80
+ class BCDD::Result::Context::Expectations < BCDD::Result::Expectations
81
+ def self.mixin_module: -> singleton(BCDD::Result::Context::Expectations::Mixin)
82
+
83
+ def self.result_factory_without_expectations: -> singleton(BCDD::Result)
84
+
85
+ def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
86
+ def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
87
+ end
88
+
89
+ module BCDD::Result::Context::Expectations::Mixin
90
+ Methods: singleton(BCDD::Result::Expectations::Mixin::Methods)
91
+ Factory: singleton(BCDD::Result::Expectations::Mixin::Factory)
92
+
93
+ module Addons
94
+ module Continuable
95
+ private def Continue: (**untyped) -> BCDD::Result::Context::Success
96
+ end
97
+
98
+ OPTIONS: Hash[Symbol, Module]
99
+
100
+ def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
101
+ end
102
+ end
@@ -0,0 +1,119 @@
1
+ module BCDD::Result::Contract
2
+ NONE: BCDD::Result::Contract::Evaluator
3
+
4
+ def self.evaluate: (
5
+ BCDD::Result::Data,
6
+ BCDD::Result::Contract::Evaluator
7
+ ) -> BCDD::Result::Contract::TypeChecker
8
+
9
+ ToEnsure: ^(Hash[Symbol, untyped] | Array[Symbol], Hash[Symbol, Hash[Symbol, bool]])
10
+ -> BCDD::Result::Contract::Interface
11
+
12
+ def self.new: (
13
+ success: Hash[Symbol, untyped] | Array[Symbol],
14
+ failure: Hash[Symbol, untyped] | Array[Symbol],
15
+ config: Hash[Symbol, Hash[Symbol, bool]]
16
+ ) -> BCDD::Result::Contract::Evaluator
17
+ end
18
+
19
+ module BCDD::Result::Contract
20
+ class TypeChecker
21
+ attr_reader result_type: Symbol
22
+ attr_reader expectations: BCDD::Result::Contract::Evaluator
23
+
24
+ def initialize: (
25
+ Symbol,
26
+ expectations: BCDD::Result::Contract::Evaluator
27
+ ) -> void
28
+
29
+ def allow?: (Array[Symbol]) -> bool
30
+ def allow_success?: (Array[Symbol]) -> bool
31
+ def allow_failure?: (Array[Symbol]) -> bool
32
+
33
+ private
34
+
35
+ def validate: (
36
+ Array[Symbol],
37
+ expected: BCDD::Result::Contract::Interface,
38
+ allow_empty: bool
39
+ ) -> bool
40
+ end
41
+ end
42
+
43
+ class BCDD::Result::Contract::Error < BCDD::Result::Error
44
+ class UnexpectedType < BCDD::Result::Contract::Error
45
+ def self.build: (type: Symbol, allowed_types: Set[Symbol])
46
+ -> BCDD::Result::Contract::Error::UnexpectedType
47
+ end
48
+
49
+ class UnexpectedValue < BCDD::Result::Contract::Error
50
+ def self.build: (type: Symbol, value: untyped, ?cause: Exception)
51
+ -> BCDD::Result::Contract::Error::UnexpectedValue
52
+ end
53
+ end
54
+
55
+ module BCDD::Result::Contract
56
+ module Interface
57
+ def ==: (BCDD::Result::Contract::Interface) -> bool
58
+
59
+ def allowed_types: -> Set[Symbol]
60
+
61
+ def type?: (Symbol) -> bool
62
+
63
+ def type!: (Symbol) -> Symbol
64
+
65
+ def type_and_value!: (BCDD::Result::Data) -> void
66
+
67
+ def !=: (untyped) -> bool
68
+ end
69
+ end
70
+
71
+ module BCDD::Result::Contract
72
+ module Disabled
73
+ extend Interface
74
+
75
+ EMPTY_SET: Set[Symbol]
76
+ end
77
+ end
78
+
79
+ module BCDD::Result::Contract
80
+ class ForTypes
81
+ include Interface
82
+
83
+ def initialize: (Array[Symbol]) -> void
84
+ end
85
+ end
86
+
87
+ module BCDD::Result::Contract
88
+ class ForTypesAndValues
89
+ include Interface
90
+
91
+ def initialize: (
92
+ Hash[Symbol, untyped],
93
+ Hash[Symbol, Hash[Symbol, bool]]
94
+ ) -> void
95
+
96
+ private
97
+
98
+ def nil_as_valid_value_checking?: -> bool
99
+ end
100
+ end
101
+
102
+ module BCDD::Result::Contract
103
+ class Evaluator
104
+ include Interface
105
+
106
+ attr_reader allowed_types: Set[Symbol]
107
+ attr_reader success: BCDD::Result::Contract::Interface
108
+ attr_reader failure: BCDD::Result::Contract::Interface
109
+
110
+ def initialize: (
111
+ BCDD::Result::Contract::Interface,
112
+ BCDD::Result::Contract::Interface
113
+ ) -> void
114
+
115
+ private
116
+
117
+ def for: (BCDD::Result::Data) -> BCDD::Result::Contract::Interface
118
+ end
119
+ end
@@ -0,0 +1,16 @@
1
+ class BCDD::Result
2
+ class Data
3
+ attr_reader kind: Symbol
4
+ attr_reader type: Symbol
5
+ attr_reader value: untyped
6
+ attr_reader to_h: Hash[Symbol, untyped]
7
+ attr_reader to_a: [Symbol, Symbol, untyped]
8
+
9
+ def initialize: (Symbol, Symbol, untyped) -> void
10
+
11
+ def inspect: -> String
12
+
13
+ alias to_ary to_a
14
+ alias to_hash to_h
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ class BCDD::Result
2
+ class Error < StandardError
3
+ def self.build: (**untyped) -> BCDD::Result::Error
4
+
5
+ class NotImplemented < BCDD::Result::Error
6
+ end
7
+
8
+ class MissingTypeArgument < BCDD::Result::Error
9
+ end
10
+
11
+ class UnexpectedOutcome < BCDD::Result::Error
12
+ def self.build: (outcome: untyped, origin: Symbol, ?expected: String)
13
+ -> BCDD::Result::Error::UnexpectedOutcome
14
+ end
15
+
16
+ class InvalidResultSubject < BCDD::Result::Error
17
+ def self.build: (given_result: BCDD::Result, expected_subject: untyped)
18
+ -> BCDD::Result::Error::InvalidResultSubject
19
+ end
20
+
21
+ class InvalidSubjectMethodArity < BCDD::Result::Error
22
+ def self.build: (subject: untyped, method: Method, max_arity: Integer)
23
+ -> BCDD::Result::Error::InvalidSubjectMethodArity
24
+ end
25
+
26
+ class UnhandledTypes < BCDD::Result::Error
27
+ def self.build: (types: Set[Symbol])
28
+ -> BCDD::Result::Error::UnhandledTypes
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ class BCDD::Result::Expectations
2
+ def self.mixin: (
3
+ ?config: Hash[Symbol, Hash[Symbol, bool]],
4
+ ?success: Hash[Symbol, untyped] | Array[Symbol],
5
+ ?failure: Hash[Symbol, untyped] | Array[Symbol]
6
+ ) -> Module
7
+
8
+ def self.mixin!: (
9
+ ?config: Hash[Symbol, Hash[Symbol, bool]],
10
+ ?success: Hash[Symbol, untyped] | Array[Symbol],
11
+ ?failure: Hash[Symbol, untyped] | Array[Symbol]
12
+ ) -> Module
13
+
14
+ def self.mixin_module: -> singleton(BCDD::Result::Expectations::Mixin)
15
+
16
+ def self.result_factory_without_expectations: -> singleton(BCDD::Result)
17
+
18
+ def self.new: (
19
+ ?subject: untyped,
20
+ ?contract: BCDD::Result::Contract::Evaluator,
21
+ ?halted: bool,
22
+ **untyped
23
+ ) -> (BCDD::Result::Expectations | untyped)
24
+
25
+ def initialize: (
26
+ ?subject: untyped,
27
+ ?contract: BCDD::Result::Contract::Evaluator,
28
+ ?halted: bool,
29
+ **untyped
30
+ ) -> void
31
+
32
+ def Success: (Symbol, ?untyped) -> BCDD::Result::Success
33
+ def Failure: (Symbol, ?untyped) -> BCDD::Result::Failure
34
+
35
+ def with: (subject: untyped) -> BCDD::Result::Expectations
36
+
37
+ private
38
+
39
+ def _ResultAs: (singleton(BCDD::Result), Symbol, untyped) -> untyped
40
+
41
+ attr_reader subject: untyped
42
+ attr_reader contract: BCDD::Result::Contract::Evaluator
43
+ attr_reader halted: bool
44
+ end
45
+
46
+ module BCDD::Result::Expectations::Mixin
47
+ module Factory
48
+ def self.module!: -> Module
49
+ end
50
+
51
+ module Methods
52
+ BASE: String
53
+ FACTORY: String
54
+
55
+ def self.to_eval: (Hash[Symbol, untyped]) -> String
56
+ end
57
+
58
+ module Addons
59
+ module Continuable
60
+ private def Continue: (untyped) -> BCDD::Result::Success
61
+ end
62
+
63
+ OPTIONS: Hash[Symbol, Module]
64
+
65
+ def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
66
+ end
67
+ end