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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +34 -11
- data/README.md +170 -5
- data/Steepfile +2 -2
- data/lib/bcdd/result/config/switchers/addons.rb +20 -0
- data/lib/bcdd/result/config/{constant_alias.rb → switchers/constant_aliases.rb} +4 -4
- data/lib/bcdd/result/config/switchers/features.rb +28 -0
- data/lib/bcdd/result/config/switchers/pattern_matching.rb +20 -0
- data/lib/bcdd/result/config.rb +8 -28
- data/lib/bcdd/result/context/failure.rb +1 -1
- data/lib/bcdd/result/context/success.rb +2 -2
- data/lib/bcdd/result/context.rb +12 -11
- data/lib/bcdd/result/transitions/tracking/disabled.rb +17 -0
- data/lib/bcdd/result/transitions/tracking/enabled.rb +80 -0
- data/lib/bcdd/result/transitions/tracking.rb +20 -0
- data/lib/bcdd/result/transitions/tree.rb +95 -0
- data/lib/bcdd/result/transitions.rb +30 -0
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +35 -18
- data/sig/bcdd/result/config.rbs +100 -0
- data/sig/bcdd/result/context.rbs +102 -0
- data/sig/bcdd/result/contract.rbs +119 -0
- data/sig/bcdd/result/data.rbs +16 -0
- data/sig/bcdd/result/error.rbs +31 -0
- data/sig/bcdd/result/expectations.rbs +67 -0
- data/sig/bcdd/result/handler.rbs +47 -0
- data/sig/bcdd/result/mixin.rbs +37 -0
- data/sig/bcdd/result/transitions.rbs +89 -0
- data/sig/bcdd/result/version.rbs +5 -0
- data/sig/bcdd/result.rbs +6 -516
- metadata +22 -4
@@ -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
|
data/lib/bcdd/result/version.rb
CHANGED
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 &&
|
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
|
-
|
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
|
142
|
+
def call_and_then_subject_method(method_name, context_data)
|
143
143
|
method = subject.method(method_name)
|
144
144
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
-
|
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
|