smart_types 0.1.0.alpha5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/CHANGELOG.md +46 -0
  4. data/Gemfile.lock +80 -52
  5. data/README.md +437 -27
  6. data/Rakefile +1 -1
  7. data/bin/console +2 -2
  8. data/lib/smart_core/types.rb +2 -0
  9. data/lib/smart_core/types/errors.rb +16 -0
  10. data/lib/smart_core/types/primitive.rb +109 -24
  11. data/lib/smart_core/types/primitive/caster.rb +5 -2
  12. data/lib/smart_core/types/primitive/checker.rb +5 -2
  13. data/lib/smart_core/types/primitive/factory.rb +105 -8
  14. data/lib/smart_core/types/primitive/factory/definition_context.rb +142 -6
  15. data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
  16. data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
  17. data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
  18. data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
  19. data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
  20. data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
  21. data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
  22. data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
  23. data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
  24. data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
  25. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +27 -3
  26. data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
  27. data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
  28. data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
  29. data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
  30. data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
  31. data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
  32. data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
  33. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +26 -2
  34. data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
  35. data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
  36. data/lib/smart_core/types/primitive/undefined_caster.rb +7 -5
  37. data/lib/smart_core/types/primitive/validator.rb +93 -0
  38. data/lib/smart_core/types/primitive/validator/result.rb +78 -0
  39. data/lib/smart_core/types/protocol.rb +7 -0
  40. data/lib/smart_core/types/protocol/instance_of.rb +19 -0
  41. data/lib/smart_core/types/system.rb +21 -5
  42. data/lib/smart_core/types/value.rb +16 -0
  43. data/lib/smart_core/types/value/array.rb +3 -0
  44. data/lib/smart_core/types/value/big_decimal.rb +31 -0
  45. data/lib/smart_core/types/value/boolean.rb +3 -0
  46. data/lib/smart_core/types/value/class.rb +3 -0
  47. data/lib/smart_core/types/value/comparable.rb +13 -0
  48. data/lib/smart_core/types/value/date.rb +24 -0
  49. data/lib/smart_core/types/value/date_time.rb +24 -0
  50. data/lib/smart_core/types/value/enumerable.rb +13 -0
  51. data/lib/smart_core/types/value/enumerator.rb +13 -0
  52. data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
  53. data/lib/smart_core/types/value/float.rb +9 -2
  54. data/lib/smart_core/types/value/hash.rb +11 -1
  55. data/lib/smart_core/types/value/integer.rb +13 -3
  56. data/lib/smart_core/types/value/io.rb +13 -0
  57. data/lib/smart_core/types/value/method.rb +9 -0
  58. data/lib/smart_core/types/value/module.rb +3 -0
  59. data/lib/smart_core/types/value/nil.rb +3 -3
  60. data/lib/smart_core/types/value/numeric.rb +16 -3
  61. data/lib/smart_core/types/value/proc.rb +14 -1
  62. data/lib/smart_core/types/value/range.rb +9 -0
  63. data/lib/smart_core/types/value/rational.rb +13 -0
  64. data/lib/smart_core/types/value/set.rb +21 -0
  65. data/lib/smart_core/types/value/string.rb +10 -1
  66. data/lib/smart_core/types/value/string_io.rb +15 -0
  67. data/lib/smart_core/types/value/symbol.rb +10 -1
  68. data/lib/smart_core/types/value/text.rb +21 -4
  69. data/lib/smart_core/types/value/time.rb +24 -0
  70. data/lib/smart_core/types/value/time_based.rb +32 -0
  71. data/lib/smart_core/types/value/unbound_method.rb +9 -0
  72. data/lib/smart_core/types/variadic.rb +7 -0
  73. data/lib/smart_core/types/variadic/tuple.rb +23 -0
  74. data/lib/smart_core/types/version.rb +2 -2
  75. data/smart_types.gemspec +6 -5
  76. metadata +69 -23
  77. data/.travis.yml +0 -20
  78. data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
  79. data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
  80. data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
  81. data/lib/smart_core/types/system/definition_dsl.rb +0 -40
  82. data/lib/smart_core/types/system/producer_dsl.rb +0 -30
data/Rakefile CHANGED
@@ -11,8 +11,8 @@ require 'rubocop-rake'
11
11
  RuboCop::RakeTask.new(:rubocop) do |t|
12
12
  config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
13
13
  t.options = ['--config', config_path]
14
- t.requires << 'rubocop-performance'
15
14
  t.requires << 'rubocop-rspec'
15
+ t.requires << 'rubocop-performance'
16
16
  t.requires << 'rubocop-rake'
17
17
  end
18
18
 
@@ -4,5 +4,5 @@
4
4
  require 'bundler/setup'
5
5
  require 'smart_core/types'
6
6
 
7
- require 'irb'
8
- IRB.start(__FILE__)
7
+ require 'pry'
8
+ Pry.start
@@ -10,4 +10,6 @@ module SmartCore::Types
10
10
  require_relative 'types/system'
11
11
  require_relative 'types/primitive'
12
12
  require_relative 'types/value'
13
+ require_relative 'types/protocol'
14
+ require_relative 'types/variadic'
13
15
  end
@@ -13,6 +13,18 @@ module SmartCore::Types
13
13
  # @since 0.1.0
14
14
  NameError = Class.new(SmartCore::NameError)
15
15
 
16
+ # @api public
17
+ # @since 0.3.0
18
+ TypeDefinitionError = Class.new(ArgumentError)
19
+
20
+ # @api public
21
+ # @since 0.3.0
22
+ IncorrectRuntimeAttributesError = Class.new(TypeDefinitionError)
23
+
24
+ # @api public
25
+ # @since 0.3.0
26
+ RuntimeAttriburtesUnsupportedError = Class.new(TypeDefinitionError)
27
+
16
28
  # @api public
17
29
  # @since 0.1.0
18
30
  TypeError = Class.new(SmartCore::TypeError)
@@ -21,6 +33,10 @@ module SmartCore::Types
21
33
  # @since 0.1.0
22
34
  TypeCastingError = Class.new(Error)
23
35
 
36
+ # @api public
37
+ # @since 0.1.0
38
+ TypeCastingUnsupportedError = Class.new(TypeCastingError)
39
+
24
40
  # @api public
25
41
  # @since 0.1.0
26
42
  NoCheckerDefinitionError = Class.new(Error)
@@ -2,26 +2,61 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive
7
+ require_relative 'primitive/checker'
6
8
  require_relative 'primitive/caster'
9
+ require_relative 'primitive/runtime_attributes_checker'
7
10
  require_relative 'primitive/undefined_caster'
8
- require_relative 'primitive/checker'
9
- require_relative 'primitive/nilable_checker'
10
- require_relative 'primitive/sum_checker'
11
- require_relative 'primitive/mult_checker'
11
+ require_relative 'primitive/invariant_control'
12
+ require_relative 'primitive/validator'
12
13
  require_relative 'primitive/factory'
14
+ require_relative 'primitive/sum_validator'
13
15
  require_relative 'primitive/sum_factory'
16
+ require_relative 'primitive/mult_validator'
14
17
  require_relative 'primitive/mult_factory'
18
+ require_relative 'primitive/nilable_validator'
15
19
  require_relative 'primitive/nilable_factory'
16
20
 
17
- # @since 0.1.0
18
- include SmartCore::Types::System::ProducerDSL
21
+ class << self
22
+ # @param type_name [String, Symbol]
23
+ # @param type_definition [Block]
24
+ # @yield [type]
25
+ # @yieldparam type [SmartCore::Types::Primitive::DefinitionContext]
26
+ # @yieldreturn [void]
27
+ # @return [SmartCore::Types::Primitive]
28
+ #
29
+ # @api public
30
+ # @since 0.1.0
31
+ def define_type(type_name, &type_definition)
32
+ self::Factory.create_type(self, type_name, type_definition)
33
+ end
34
+ end
35
+
36
+ # @note NilClass is suitable for sum-types, mult-types and nilable types.
37
+ # @return [String, NilClass]
38
+ #
39
+ # @api public
40
+ # @since 0.2.0
41
+ attr_reader :name
19
42
 
20
- # @return [SmartCore::Types::Primitive::Checker]
43
+ # @return [Class<SmartCore::Types::Primitive>]
21
44
  #
22
45
  # @api private
23
- # @since 0.1.0
24
- attr_reader :checker
46
+ # @since 0.3.0
47
+ attr_reader :category
48
+
49
+ # @return [Array<Any>]
50
+ #
51
+ # @api private
52
+ # @since 0.3.0
53
+ attr_reader :runtime_attributes
54
+
55
+ # @return [SmartCore::Types::Primitive::RuntimeAttributesChecker]
56
+ #
57
+ # @api private
58
+ # @since 0.3.0
59
+ attr_reader :runtime_attributes_checker
25
60
 
26
61
  # @return [SmartCore::Types::Primitive::Caster]
27
62
  #
@@ -29,25 +64,53 @@ class SmartCore::Types::Primitive
29
64
  # @since 0.1.0
30
65
  attr_reader :caster
31
66
 
32
- # @return [String]
67
+ # @return [SmartCore::Types::Primitive::Validator]
68
+ # @return [SmartCore::Types::Primitive::SumValidator]
69
+ # @return [SmartCore::Types::Primitive::MultValidator]
70
+ # @return [SmartCore::Types::primitive::NilableValidator]
33
71
  #
34
72
  # @api private
35
- # @since 0.1.0
36
- attr_reader :name
73
+ # @since 0.2.0
74
+ attr_reader :validator
37
75
 
38
- # @param checker [SmartCore::Types::Primitive::Checker]
76
+ # @param name [String, NilClass] NilClass is suitable for sum-types, mult-types and nilable types.
77
+ # @param category [Class<SmartCore::Types::Primitive>, NilClass]
78
+ # @param validator [
79
+ # SmartCore::Types::Primitive::Validator,
80
+ # SmartCore::Types::Primitive::SumValidator,
81
+ # SmartCore::Types::Primitive::MultValidator,
82
+ # SmartCore::Types::Primitive::NilableValidator
83
+ # ]
39
84
  # @param caster [SmartCore::Types::Primitive::Caster]
40
- # @param name [String]
85
+ # @param runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
86
+ # @param runtime_attributes [Array<Any>]
41
87
  # @return [void]
42
88
  #
43
89
  # @api private
44
90
  # @since 0.1.0
45
- def initialize(checker, caster, name)
46
- @lock = SmartCore::Engine::Lock.new
47
- @checker = checker
91
+ # @version 0.3.0
92
+ # rubocop:disable Metrics/ParameterLists
93
+ def initialize(name, category, validator, caster, runtime_attributes_checker, *runtime_attributes)
94
+ @name = name
95
+ @category = category
96
+ @validator = validator
48
97
  @caster = caster
49
98
  @nilable = nil
50
- @name = name.freeze
99
+ @runtime_attributes_checker = runtime_attributes_checker
100
+ @runtime_attributes = runtime_attributes
101
+ @lock = SmartCore::Engine::Lock.new
102
+ end
103
+ # rubocop:enable Metrics/ParameterLists
104
+
105
+ # @param cloneable_instance [SmartCore::Types::Primitive]
106
+ # @return [SmartCore::Types::Primitive]
107
+ #
108
+ # @api private
109
+ # @since 0.3.0
110
+ def initialize_copy(cloneable_instance)
111
+ lock.synchronize do
112
+ self.class::Factory::RuntimeTypeBuilder.initialize_clone(self, cloneable_instance)
113
+ end
51
114
  end
52
115
 
53
116
  # @param value [Any]
@@ -55,20 +118,38 @@ class SmartCore::Types::Primitive
55
118
  #
56
119
  # @api public
57
120
  # @since 0.1.0
121
+ # @since 0.2.0
58
122
  def valid?(value)
59
- checker.call(value)
123
+ validator.valid?(value)
60
124
  end
61
125
 
126
+ # @param value [Any]
62
127
  # @return [void]
63
128
  #
64
- # @raise [SmartCore::TypeError]
129
+ # @raise [SmartCore::Types::TypeError]
130
+ # @see SmartCore::Primitive::Validator
131
+ # @see SmartCore::Primitive::MultValidator
132
+ # @see SmartCore::Primitive::SumValidator
133
+ # @see SmartCore::Primitive::NilableValidator
65
134
  #
66
135
  # @api public
67
136
  # @since 0.1.0
137
+ # @version 0.2.0
68
138
  def validate!(value)
69
- valid?(value) || raise(SmartCore::Types::TypeError, <<~ERROR_MESSAGE)
70
- Invalid type (given #{(class << value; superclass; end).name}, expects #{name}/SmartCore)
71
- ERROR_MESSAGE
139
+ validator.validate!(value)
140
+ end
141
+
142
+ # @return [SmartCore::Types::Primitive::Validator::Result]
143
+ #
144
+ # @see SmartCore::Primitive::Validator
145
+ # @see SmartCore::Primitive::MultValidator
146
+ # @see SmartCore::Primitive::SumValidator
147
+ # @see SmartCore::Primitive::NilableValidator
148
+ #
149
+ # @api public
150
+ # @since 0.2.0
151
+ def validate(value)
152
+ validator.validate(value)
72
153
  end
73
154
 
74
155
  # @param value [Any]
@@ -76,8 +157,12 @@ class SmartCore::Types::Primitive
76
157
  #
77
158
  # @api public
78
159
  # @since 0.1.0
160
+ # @version 0.3.0
79
161
  def cast(value)
80
- caster.call(value)
162
+ # TODO (0.x.0):
163
+ # refactor with ValueTransformer with internal reference to the type object
164
+ # in Validator manner (in order to avoid explicit #runtime_attributes passing)
165
+ caster.call(value, runtime_attributes)
81
166
  end
82
167
 
83
168
  # @return [SmartCore::Types::Primitive]
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::Caster
6
7
  # @param expression [Proc]
7
8
  # @return [void]
@@ -13,12 +14,14 @@ class SmartCore::Types::Primitive::Caster
13
14
  end
14
15
 
15
16
  # @param value [Any]
17
+ # @param runtime_attributes [Array<Any>]
16
18
  # @return [Any]
17
19
  #
18
20
  # @api private
19
21
  # @since 0.1.0
20
- def call(value)
21
- expression.call(value)
22
+ # @version 0.3.0
23
+ def call(value, runtime_attributes)
24
+ expression.call(value, runtime_attributes)
22
25
  end
23
26
 
24
27
  private
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::Checker
6
7
  # @param expression [Proc]
7
8
  # @return [void]
@@ -13,12 +14,14 @@ class SmartCore::Types::Primitive::Checker
13
14
  end
14
15
 
15
16
  # @param value [Any]
17
+ # @param runtime_attributes [Array<Any>]
16
18
  # @return [Boolean]
17
19
  #
18
20
  # @api private
19
21
  # @since 0.1.0
20
- def call(value)
21
- !!expression.call(value)
22
+ # @version 0.3.0
23
+ def call(value, runtime_attributes)
24
+ !!expression.call(value, runtime_attributes)
22
25
  end
23
26
 
24
27
  private
@@ -2,8 +2,10 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::Factory
6
7
  require_relative 'factory/definition_context'
8
+ require_relative 'factory/runtime_type_builder'
7
9
 
8
10
  class << self
9
11
  # @param type_category [Class<SmartCore::Types::Primitive>]
@@ -13,12 +15,26 @@ class SmartCore::Types::Primitive::Factory
13
15
  #
14
16
  # @api private
15
17
  # @since 0.1.0
18
+ # @version 0.3.0
16
19
  def create_type(type_category, type_name, type_definition)
17
20
  type_definitions = build_type_definitions(type_definition)
21
+ type_runtime_attributes_checker = build_type_runtime_attributes_checker(type_definitions)
18
22
  type_checker = build_type_checker(type_definitions)
19
23
  type_caster = build_type_caster(type_definitions)
20
- type = build_type(type_category, type_name, type_checker, type_caster)
21
- type.tap { register_new_type(type_category, type_name, type) }
24
+ type_invariant_control = build_type_invariant_control(type_definitions)
25
+ type_validator = build_type_validator(type_checker, type_invariant_control)
26
+ build_type(
27
+ type_category,
28
+ type_name,
29
+ type_validator,
30
+ type_caster,
31
+ type_runtime_attributes_checker
32
+ ).tap do |type|
33
+ assign_type_validator(type, type_validator)
34
+ assign_type_runtime_attributes_checker(type, type_runtime_attributes_checker)
35
+ register_new_type(type_category, type_name, type)
36
+ register_runtime_type_builder(type_category, type_name)
37
+ end
22
38
  end
23
39
 
24
40
  private
@@ -37,11 +53,34 @@ class SmartCore::Types::Primitive::Factory
37
53
  end.tap do |context|
38
54
  raise(
39
55
  SmartCore::Types::NoCheckerDefinitionError,
40
- 'Type checker is not provided (use .define_checker for it)'
41
- ) if context.type_checker.nil?
56
+ 'Type checker is not provided. You should define it via .define_checker(&block)'
57
+ ) if context.type_checker == nil
42
58
  end
43
59
  end
44
60
 
61
+ # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
62
+ # @return [SmartCore::Types::Primitive::RuntimeAttributesChecker]
63
+ #
64
+ # @api private
65
+ # @since 0.3.0
66
+ def build_type_runtime_attributes_checker(type_definitions)
67
+ SmartCore::Types::Primitive::RuntimeAttributesChecker.new(
68
+ type_definitions.type_runtime_attributes_checker
69
+ )
70
+ end
71
+
72
+ # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
73
+ # @return [SmartCore::Types::Primitive::InvariantControl]
74
+ #
75
+ # @api private
76
+ # @since 0.2.0
77
+ def build_type_invariant_control(type_definitions)
78
+ SmartCore::Types::Primitive::InvariantControl.create(
79
+ type_definitions.type_invariant_chains,
80
+ type_definitions.type_invariants
81
+ )
82
+ end
83
+
45
84
  # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
46
85
  # @return [SmartCore::Types::Primitive::Checker]
47
86
  #
@@ -57,23 +96,67 @@ class SmartCore::Types::Primitive::Factory
57
96
  # @api private
58
97
  # @since 0.1.0
59
98
  def build_type_caster(type_definitions)
60
- if type_definitions.type_caster.nil?
99
+ if type_definitions.type_caster == nil
61
100
  SmartCore::Types::Primitive::UndefinedCaster.new
62
101
  else
63
102
  SmartCore::Types::Primitive::Caster.new(type_definitions.type_caster)
64
103
  end
65
104
  end
66
105
 
106
+ # @param checker [SmartCore::Types::Primitive::Checker]
107
+ # @param invariant_control [SmartCore::Types::Primitive::InvariantControl]
108
+ # @return [void]
109
+ #
110
+ # @api private
111
+ # @since 0.2.0
112
+ def build_type_validator(type_checker, type_invariant_control)
113
+ SmartCore::Types::Primitive::Validator.new(type_checker, type_invariant_control)
114
+ end
115
+
67
116
  # @param type_klass [Class<SmartCore::Types::Primitive>]
68
117
  # @param type_name [String, Symbol]
69
- # @param type_checker [SmartCore::Types::Primitive::Checker]
118
+ # @param type_validator [SmartCore::Types::Primitive::Validator]
70
119
  # @param type_caster [SmartCore::Types::Primitive::Caster]
120
+ # @param type_runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
71
121
  # @return [SmartCore::Types::Primitive]
72
122
  #
73
123
  # @api private
74
124
  # @since 0.1.0
75
- def build_type(type_category, type_name, type_checker, type_caster)
76
- Class.new(type_category).new(type_checker, type_caster, type_name.to_s)
125
+ # @version 0.3.0
126
+ def build_type(
127
+ type_category,
128
+ type_name,
129
+ type_validator,
130
+ type_caster,
131
+ type_runtime_attributes_checker
132
+ )
133
+ Class.new(type_category).new(
134
+ type_name,
135
+ type_category,
136
+ type_validator,
137
+ type_caster,
138
+ type_runtime_attributes_checker
139
+ )
140
+ end
141
+
142
+ # @param type [SmartCore::Types::Primitive]
143
+ # @param type_validator [SmartCore::Types::Primitive::Validator]
144
+ # @return [void]
145
+ #
146
+ # @api private
147
+ # @since 0.2.0
148
+ def assign_type_validator(type, type_validator)
149
+ type_validator.___assign_type___(type)
150
+ end
151
+
152
+ # @param type [SmartCore::Types::Primitive]
153
+ # @param type_runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
154
+ # @return [void]
155
+ #
156
+ # @api private
157
+ # @since 0.3.0
158
+ def assign_type_runtime_attributes_checker(type, type_runtime_attributes_checker)
159
+ type_runtime_attributes_checker.___assign_type___(type)
77
160
  end
78
161
 
79
162
  # @param type_category [Class<SmartCore::Types::Primitive>]
@@ -93,5 +176,19 @@ class SmartCore::Types::Primitive::Factory
93
176
  "Incorrect constant name for new type (#{type_name})"
94
177
  )
95
178
  end
179
+
180
+ # @param type_category [Class<SmartCore::Types::Primitive>]
181
+ # @param type_name [String, Symbol]
182
+ # @return [void]
183
+ #
184
+ # @raise [SmartCore::Types::IncorrectTypeNameError]
185
+ #
186
+ # @api private
187
+ # @since 0.3.0
188
+ def register_runtime_type_builder(type_category, type_name)
189
+ type_category.define_singleton_method(type_name) do |*runtime_attributes|
190
+ RuntimeTypeBuilder.build_with_runtime(type_name, type_category, runtime_attributes)
191
+ end
192
+ end
96
193
  end
97
194
  end