smart_types 0.1.0.alpha3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/.travis.yml +6 -5
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile.lock +74 -48
  6. data/README.md +292 -22
  7. data/Rakefile +1 -1
  8. data/bin/console +2 -2
  9. data/lib/smart_core/types/errors.rb +4 -0
  10. data/lib/smart_core/types/primitive.rb +67 -20
  11. data/lib/smart_core/types/primitive/factory.rb +48 -8
  12. data/lib/smart_core/types/primitive/factory/definition_context.rb +116 -6
  13. data/lib/smart_core/types/primitive/invariant_control.rb +64 -0
  14. data/lib/smart_core/types/primitive/invariant_control/chain.rb +58 -0
  15. data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
  16. data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
  17. data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
  18. data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
  19. data/lib/smart_core/types/primitive/invariant_control/single.rb +54 -0
  20. data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
  21. data/lib/smart_core/types/primitive/mult_factory.rb +25 -10
  22. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +5 -3
  23. data/lib/smart_core/types/primitive/mult_validator.rb +34 -0
  24. data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
  25. data/lib/smart_core/types/primitive/nilable_factory.rb +24 -9
  26. data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
  27. data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
  28. data/lib/smart_core/types/primitive/sum_factory.rb +25 -10
  29. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +4 -2
  30. data/lib/smart_core/types/primitive/sum_validator.rb +101 -0
  31. data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
  32. data/lib/smart_core/types/primitive/undefined_caster.rb +3 -4
  33. data/lib/smart_core/types/primitive/validator.rb +84 -0
  34. data/lib/smart_core/types/primitive/validator/result.rb +78 -0
  35. data/lib/smart_core/types/system.rb +21 -5
  36. data/lib/smart_core/types/value.rb +17 -0
  37. data/lib/smart_core/types/value/big_decimal.rb +28 -0
  38. data/lib/smart_core/types/value/comparable.rb +13 -0
  39. data/lib/smart_core/types/value/date.rb +21 -0
  40. data/lib/smart_core/types/value/date_time.rb +21 -0
  41. data/lib/smart_core/types/value/enumerable.rb +13 -0
  42. data/lib/smart_core/types/value/enumerator.rb +13 -0
  43. data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
  44. data/lib/smart_core/types/value/float.rb +6 -2
  45. data/lib/smart_core/types/value/hash.rb +8 -1
  46. data/lib/smart_core/types/value/integer.rb +10 -3
  47. data/lib/smart_core/types/value/io.rb +13 -0
  48. data/lib/smart_core/types/value/method.rb +9 -0
  49. data/lib/smart_core/types/value/nil.rb +9 -0
  50. data/lib/smart_core/types/value/numeric.rb +13 -3
  51. data/lib/smart_core/types/value/proc.rb +11 -1
  52. data/lib/smart_core/types/value/range.rb +9 -0
  53. data/lib/smart_core/types/value/rational.rb +13 -0
  54. data/lib/smart_core/types/value/set.rb +13 -0
  55. data/lib/smart_core/types/value/string.rb +7 -1
  56. data/lib/smart_core/types/value/string_io.rb +13 -0
  57. data/lib/smart_core/types/value/symbol.rb +7 -1
  58. data/lib/smart_core/types/value/text.rb +16 -1
  59. data/lib/smart_core/types/value/time.rb +21 -0
  60. data/lib/smart_core/types/value/time_based.rb +29 -0
  61. data/lib/smart_core/types/value/unbound_method.rb +9 -0
  62. data/lib/smart_core/types/version.rb +2 -2
  63. data/smart_types.gemspec +6 -5
  64. metadata +64 -22
  65. data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
  66. data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
  67. data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
  68. data/lib/smart_core/types/system/definition_dsl.rb +0 -40
  69. data/lib/smart_core/types/system/producer_dsl.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc4e623d3f8d313b11dbd7e483989b3f2b94904a9e3a1ec27edb85095fdc418b
4
- data.tar.gz: 3514c7ecfcd83963744f66ce92dfd648bd680b61ad34aaf4c2b0a9207cd842ad
3
+ metadata.gz: d5f0c7f2b54ceaa7fe20e85d7d280b64b8310eb5f4fa802d11052074e6b10f96
4
+ data.tar.gz: 021c3c6194fb4f54246f4a44a7c548ce9da0790a66b95e0a060547e73efeaf3f
5
5
  SHA512:
6
- metadata.gz: a21d4a5a20575cba14a000440c6da87aab465b2aa7c02b2697f13c422fc3c6dbe873c4b2d0fcfec1e5ee182db7a356b8ca0f3bf7beae0f5787b10610d4a3bfca
7
- data.tar.gz: 80c82999c44edab7225b5169cbff0586254c5d817efbfb4c5df4f6906f0b794280dd52c7342fe732b30a6b339c96cf24b40d8c79915a679b87fca9e91a3ac6fa
6
+ metadata.gz: 6e2fc86bcea2292570d2c51e9b95ead6ecc30f8251db75a61fda088c1a84bdb15cea65fdc478728869fb5e5e56b7cddb774938cae38c60e4dee70197e6c1c7f3
7
+ data.tar.gz: c7b27e2f70f3f8eac851f63365b3287a2c7aeb8f7f999679daa715d5ff7de93b32bd6204ea67f6af2c2ea1e5ccd569027051674c9266c62ff7d425c55692619a
@@ -5,7 +5,8 @@ inherit_gem:
5
5
  - lib/rubocop.rspec.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 2.4.9
8
+ TargetRubyVersion: 2.7.2
9
+ NewCops: enable
9
10
  Include:
10
11
  - lib/**/*.rb
11
12
  - spec/**/*.rb
@@ -13,3 +14,11 @@ AllCops:
13
14
  - Rakefile
14
15
  - smart_types.gemspec
15
16
  - bin/console
17
+
18
+ # NOTE: support for old ruby versions
19
+ Style/RedundantBegin:
20
+ Enabled: false
21
+
22
+ # NOTE: used only in specs and it is ok in specs
23
+ Lint/EmptyBlock:
24
+ Enabled: false
@@ -2,17 +2,18 @@
2
2
  language: ruby
3
3
  cache: bundler
4
4
  os: linux
5
- before_install: gem install bundler -v 2.1.2
5
+ dist: xenial
6
+ before_install: gem install bundler
6
7
  script:
7
8
  - bundle exec rake rubocop
8
9
  - bundle exec rake rspec
9
10
  jobs:
10
11
  fast_finish: true
11
12
  include:
12
- - rvm: 2.4.9
13
- - rvm: 2.5.7
14
- - rvm: 2.6.5
15
- - rvm: 2.7.0
13
+ - rvm: 2.4.10
14
+ - rvm: 2.5.8
15
+ - rvm: 2.6.6
16
+ - rvm: 2.7.1
16
17
  - rvm: ruby-head
17
18
  - rvm: jruby-head
18
19
  allow_failures:
@@ -1,2 +1,19 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
+
4
+ ## [0.2.0] - 2020-11-21
5
+ ### Added
6
+ - Brand new **Type invariant API**:
7
+ - globally refactored validation logic (with backward compatability for `#valid?(value)` method);
8
+ - new type definition DSL: `.invariant(name)` and `.invariant_chain(name)`;
9
+ - chained invariants will be invoked according to the definition order (second invokation
10
+ depends on previous successful invariant check);
11
+ - new validation API: `validate(value)` (with `#errors` support based on invariant names);
12
+ - at this moment Invariant API is supported only by primitive types (type sum and type multiplication support coming soon);
13
+
14
+ ### Changed
15
+
16
+ - Updated `smart_engine` dependency (to `~> 0.7`) (need `SmartCore::Engine::Atom`);
17
+
18
+ ## [0.1.0] - 2020-05-05
19
+ - Release :)
@@ -1,77 +1,103 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_types (0.1.0.alpha3)
5
- smart_engine (~> 0.5)
4
+ smart_types (0.2.0)
5
+ smart_engine (~> 0.7)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- armitage-rubocop (0.79.0)
11
- rubocop (= 0.79.0)
12
- rubocop-performance (= 1.5.2)
13
- rubocop-rails (= 2.4.1)
14
- rubocop-rake (= 0.5.0)
15
- rubocop-rspec (= 1.37.1)
16
- ast (2.4.0)
17
- diff-lcs (1.3)
10
+ activesupport (6.0.3.4)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 0.7, < 2)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ zeitwerk (~> 2.2, >= 2.2.2)
16
+ armitage-rubocop (1.3.1.1)
17
+ rubocop (= 1.3.1)
18
+ rubocop-performance (= 1.9.0)
19
+ rubocop-rails (= 2.8.1)
20
+ rubocop-rake (= 0.5.1)
21
+ rubocop-rspec (= 2.0.0)
22
+ ast (2.4.1)
23
+ coderay (1.1.3)
24
+ concurrent-ruby (1.1.7)
25
+ diff-lcs (1.4.4)
18
26
  docile (1.3.2)
19
- jaro_winkler (1.5.4)
20
- json (2.3.0)
21
- parallel (1.19.1)
22
- parser (2.7.0.2)
23
- ast (~> 2.4.0)
24
- rack (2.1.1)
27
+ i18n (1.8.5)
28
+ concurrent-ruby (~> 1.0)
29
+ method_source (1.0.0)
30
+ minitest (5.14.2)
31
+ parallel (1.20.0)
32
+ parser (2.7.2.0)
33
+ ast (~> 2.4.1)
34
+ pry (0.13.1)
35
+ coderay (~> 1.1)
36
+ method_source (~> 1.0)
37
+ rack (2.2.3)
25
38
  rainbow (3.0.0)
26
39
  rake (13.0.1)
27
- rspec (3.9.0)
28
- rspec-core (~> 3.9.0)
29
- rspec-expectations (~> 3.9.0)
30
- rspec-mocks (~> 3.9.0)
31
- rspec-core (3.9.1)
32
- rspec-support (~> 3.9.1)
33
- rspec-expectations (3.9.0)
40
+ regexp_parser (1.8.2)
41
+ rexml (3.2.4)
42
+ rspec (3.10.0)
43
+ rspec-core (~> 3.10.0)
44
+ rspec-expectations (~> 3.10.0)
45
+ rspec-mocks (~> 3.10.0)
46
+ rspec-core (3.10.0)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-expectations (3.10.0)
34
49
  diff-lcs (>= 1.2.0, < 2.0)
35
- rspec-support (~> 3.9.0)
36
- rspec-mocks (3.9.1)
50
+ rspec-support (~> 3.10.0)
51
+ rspec-mocks (3.10.0)
37
52
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.9.0)
39
- rspec-support (3.9.2)
40
- rubocop (0.79.0)
41
- jaro_winkler (~> 1.5.1)
53
+ rspec-support (~> 3.10.0)
54
+ rspec-support (3.10.0)
55
+ rubocop (1.3.1)
42
56
  parallel (~> 1.10)
43
- parser (>= 2.7.0.1)
57
+ parser (>= 2.7.1.5)
44
58
  rainbow (>= 2.2.2, < 4.0)
59
+ regexp_parser (>= 1.8)
60
+ rexml
61
+ rubocop-ast (>= 1.1.1)
45
62
  ruby-progressbar (~> 1.7)
46
- unicode-display_width (>= 1.4.0, < 1.7)
47
- rubocop-performance (1.5.2)
48
- rubocop (>= 0.71.0)
49
- rubocop-rails (2.4.1)
63
+ unicode-display_width (>= 1.4.0, < 2.0)
64
+ rubocop-ast (1.1.1)
65
+ parser (>= 2.7.1.5)
66
+ rubocop-performance (1.9.0)
67
+ rubocop (>= 0.90.0, < 2.0)
68
+ rubocop-ast (>= 0.4.0)
69
+ rubocop-rails (2.8.1)
70
+ activesupport (>= 4.2.0)
50
71
  rack (>= 1.1)
51
- rubocop (>= 0.72.0)
52
- rubocop-rake (0.5.0)
72
+ rubocop (>= 0.87.0)
73
+ rubocop-rake (0.5.1)
53
74
  rubocop
54
- rubocop-rspec (1.37.1)
55
- rubocop (>= 0.68.1)
75
+ rubocop-rspec (2.0.0)
76
+ rubocop (~> 1.0)
77
+ rubocop-ast (>= 1.1.0)
56
78
  ruby-progressbar (1.10.1)
57
- simplecov (0.17.1)
79
+ simplecov (0.19.1)
58
80
  docile (~> 1.1)
59
- json (>= 1.8, < 3)
60
- simplecov-html (~> 0.10.0)
61
- simplecov-html (0.10.2)
62
- smart_engine (0.5.0)
63
- unicode-display_width (1.6.0)
81
+ simplecov-html (~> 0.11)
82
+ simplecov-html (0.12.3)
83
+ smart_engine (0.8.0)
84
+ thread_safe (0.3.6)
85
+ tzinfo (1.2.8)
86
+ thread_safe (~> 0.1)
87
+ unicode-display_width (1.7.0)
88
+ zeitwerk (2.4.1)
64
89
 
65
90
  PLATFORMS
66
91
  ruby
67
92
 
68
93
  DEPENDENCIES
69
- armitage-rubocop (~> 0.78)
94
+ armitage-rubocop (~> 1.3)
70
95
  bundler (~> 2.1)
96
+ pry (~> 0.13)
71
97
  rake (~> 13.0)
72
- rspec (~> 3.9)
73
- simplecov (~> 0.17)
98
+ rspec (~> 3.10)
99
+ simplecov (~> 0.19)
74
100
  smart_types!
75
101
 
76
102
  BUNDLED WITH
77
- 2.1.2
103
+ 2.1.4
data/README.md CHANGED
@@ -2,12 +2,10 @@
2
2
 
3
3
  > A set of objects that acts like types (type checking and type casting) with a support for basic type algebra.
4
4
 
5
- Full-featured type system for any ruby project. Supports custom type definitioning,
5
+ Minimalistic type system for any ruby project. Supports custom type definitioning,
6
6
  type validation, type casting and type categorizing. Provides a set of commonly used type
7
7
  categories and general purpose types. Has a flexible and simplest type definition toolchain.
8
8
 
9
- Just add and use :) Enjoy! :)
10
-
11
9
  ## Installation
12
10
 
13
11
  ```ruby
@@ -41,77 +39,349 @@ type4 = type1 & type2
41
39
 
42
40
  ## Supported types
43
41
 
44
- - Primitive Value Types:
42
+ - Primitives
45
43
 
46
44
  ```ruby
47
45
  SmartCore::Types::Value::Any
46
+ SmartCore::Types::Value::Nil
48
47
  SmartCore::Types::Value::String
49
48
  SmartCore::Types::Value::Symbol
50
49
  SmartCore::Types::Value::Text
51
50
  SmartCore::Types::Value::Integer
52
51
  SmartCore::Types::Value::Float
53
52
  SmartCore::Types::Value::Numeric
53
+ SmartCore::Types::Value::BigDecimal
54
54
  SmartCore::Types::Value::Boolean
55
55
  SmartCore::Types::Value::Array
56
56
  SmartCore::Types::Value::Hash
57
57
  SmartCore::Types::Value::Proc
58
58
  SmartCore::Types::Value::Class
59
59
  SmartCore::Types::Value::Module
60
+ SmartCore::Types::Value::Time
61
+ SmartCore::Types::Value::DateTime
62
+ SmartCore::Types::Value::Date
63
+ SmartCore::Types::Value::TimeBased
60
64
  ```
61
65
 
62
66
  ---
63
67
 
64
68
  ## Nilable types
65
69
 
70
+ - invoke `.nilable` on any type object:
71
+
66
72
  ```ruby
67
- SmartCore::Types::Value::Any.nilable
68
73
  SmartCore::Types::Value::String.nilable
69
- SmartCore::Types::Value::Symbol.nilable
70
- SmartCore::Types::Value::Text.nilable
71
- SmartCore::Types::Value::Integer.nilable
72
- SmartCore::Types::Value::Float.nilable
73
- SmartCore::Types::Value::Numeric.nilable
74
- SmartCore::Types::Value::Boolean.nilable
75
- SmartCore::Types::Value::Array.nilable
76
- SmartCore::Types::Value::Hash.nilable
77
- SmartCore::Types::Value::Proc.nilable
78
- SmartCore::Types::Value::Class.nilable
79
- SmartCore::Types::Value::Module.nilable
74
+ # -- or --
75
+ SmartCore::Types::Value::Time.nilable
76
+ # and etc.
80
77
  ```
81
78
 
82
79
  ---
83
80
 
84
- ## Type validation and type casting
81
+ ## Custom type definition
82
+
83
+ Type definition is a composition of:
84
+
85
+ - type checker (required);
86
+ - type caster (optional);
87
+ - type invariants (optional);
88
+ - type invariant chains (optional);
89
+
90
+ Invariant is a custom validation block that will work as a logical value checker. You can have as much invariants as you want.
91
+
92
+ Type invariants does not depends on each other (invariant defined out from chain does not depends on other invariants);
93
+
94
+ Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
95
+
96
+ **!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
97
+ Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
98
+
99
+ Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section). Invariant error code pattern:
100
+ - for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
101
+ - for single invariant: `TypeName.invariant_name`;
102
+
103
+ #### Primitive type definition
85
104
 
86
105
  ```ruby
87
106
  # documentation is coming
107
+
108
+ # example:
109
+ SmartCore::Types::Value.define_type(:String) do |type|
110
+ type.define_checker do |value|
111
+ value.is_a?(::String)
112
+ end
113
+
114
+ type.define_caster do |value|
115
+ value.to_s
116
+ end
117
+ end
118
+ ```
119
+
120
+ #### With type invariants
121
+
122
+ ```ruby
123
+ SmartCore::Types::Value.define_type(:String) do |type|
124
+ type.define_checker do |value|
125
+ value.is_a?(::String)
126
+ end
127
+
128
+ type.define_caster do |value|
129
+ value.to_s
130
+ end
131
+
132
+ # NOTE:
133
+ # invariant defined out from chain does not depends on other invariants
134
+ type.invariant(:uncensored_content) do |value|
135
+ !value.include?('uncensored_word')
136
+ end
137
+
138
+ type.invariant(:filled) do |value|
139
+ value != ''
140
+ end
141
+
142
+ type.invariant_chain(:password) do
143
+ invariant(:should_present) { |value| value != '' }
144
+ invariant(:should_have_numbers) { |value| v.match?(/[0-9]+/) }
145
+ # NOTE:
146
+ # inside a chain each next invariant invokation
147
+ # depends on previous successful invariant check
148
+ end
149
+ end
88
150
  ```
89
151
 
90
152
  ---
91
153
 
92
- ## Custom type definition
154
+ ## Type validation
155
+
156
+ Type validation reflects on two APIs:
157
+
158
+ - type checker ([how to define type checkers](#custom-type-definition));
159
+ - type invariants (invariants and invariant chains) ([how to define type invariants](#custom-type-definition));
160
+
161
+ Type invariants does not depends on each other (invariant defined out from the chain does not depends on other invariants);
162
+
163
+ Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
164
+
165
+ **!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
166
+ Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
167
+
168
+ Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section) and represents a set of error codes in result object;
169
+
170
+ Type valdiation interface:
171
+
172
+ - `valid?(value)` - validates value and returns `true` or `false`;
173
+ - returns `ture` only if the type checker returns `true` and all invariants are valid;
174
+ - `validate(value)` - validates value and returns the monadic result object:
175
+ - `SmartCore::Types::Primitive::Validator::Result` for primitive types;
176
+ - `SmartCore::Types::Primitive::SumValidator::Result` for sum-based types;
177
+ - `SmartCore::Types::Primitive::MultValidator::Result` for mult-based types;
178
+ - `SmartCore::Types::Primitive::NilableValidator::Result` for nilable types;
179
+ - `validate!(value)` - validates value and returns nothing (for successful validation) or
180
+ raises an exception (`SmartCore::Types::TypeError`) (for unsuccessful validation);
181
+
182
+ Validation result object interface:
183
+
184
+ - `#success?` / `#failure?` (`#success?` is a combination of `valid_check? && valid_invariants?`; `#failure?` - is an opposite of `#success?`);
185
+ - `#valid_check?` (valid type checker or not);
186
+ - `#valid_invariants?` (`false` if at least one invariant is invalid);
187
+ - `#errors` (the same as `#invariant_errors` and the same as `#error_codes`) - an array of failed invariant names;
188
+ - error code patterns:
189
+ - for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
190
+ - for single invariant: `TypeName.invariant_name`;
191
+ - `#checked_value` (the same as `#value`) - checked value :)
192
+
93
193
 
94
194
  ```ruby
95
- # documentation is coming
195
+ SmartCore::Types::Value::String.valid?('test123') # => true
196
+ SmartCore::Types::Value::String.valid?(123.45) # => false
197
+ ```
198
+
199
+ ```ruby
200
+ result = SmartCore::Types::Value::String.validate('test')
201
+
202
+ result.checked_value # => 'test'
203
+ # --- same as: ---
204
+ result.value
205
+
206
+ result.success? # => false (valid_check? && valid_invariants?)
207
+ result.failure? # => true
208
+
209
+ result.valid_check? # => true
210
+ result.valid_invariants? # => false
211
+
212
+ # invariant errors:
213
+ result.errors # => ['String.password.should_have_numbers']
214
+ # -- same as: ---
215
+ result.invariant_errors
216
+ # -- same as: ---
217
+ result.error_codes
218
+ ```
219
+
220
+ ```ruby
221
+ result = SmartCore::Types::Value::String.validate('test1234')
222
+ result.success? # => true
223
+ result.errors # => []
224
+ ```
225
+
226
+ ```ruby
227
+ SmartCore::Types::Value::String.validate!('test') # => SmartCore::Types::TypeError
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Type casting
233
+
234
+ ```
235
+ SmartCore::Types::Value::String.cast(123) # => "123"
236
+ SmartCore::Types::Value::Float.cast('55') # => 55.0
96
237
  ```
97
238
 
98
239
  ---
99
240
 
100
241
  ## Basic type algebra
101
242
 
243
+ > (type sum and type multiplication does not support invariants at this moment (in development yet));
244
+
102
245
  ```ruby
103
246
  # documentation is coming
247
+
248
+ # how to define primitive type sum:
249
+ SmartCore::Types::Value::Text = SmartCore::Types::Value::String | SmartCore::Types::Value::Symbol
250
+ SmartCore::Types::Value::Numeric = SmartCore::Types::Value::Float | SmartCore::Types::Value::Integer
251
+
252
+ # how to define primitive type multiplication:
253
+ SmartCore::Types::Value::CryptoString = SmartCore::Types::Value::NumberdString & SmartCore::Types::Value::SymbolicString
104
254
  ```
105
255
 
106
256
  ---
107
257
 
108
- ## Type system integration
258
+ ## Roadmap
259
+
260
+ - type configuration:
109
261
 
110
262
  ```ruby
111
- # documentation is coming
263
+ SmartCore::Types::Value.type(:Time) do |type|
264
+ type.configuration do |config| # config definition
265
+ setting :iso, :rfc2822
266
+ # TODO: think about a more convinient DSL
267
+ end
268
+
269
+ type.define_caster do |value, config| # config usage
270
+ case config.standard
271
+ when :rfc2822
272
+ ::Time.rfc2822(value)
273
+ else
274
+ # ...
275
+ end
276
+ end
277
+ end
112
278
  ```
113
279
 
114
- ---
280
+ - pipelined type caster definition for the sum-based types:
281
+
282
+ ```ruby
283
+ SmartCore::Types::Value::TimeLike = SmartCore::Types::System.type_sum(
284
+ SmartCore::Types::Time,
285
+ SmartCore::Types::DateTime,
286
+ SmartCore::Types::Date,
287
+ ) do |type|
288
+ type.define_caster(:pipelined) # try Time.cast => try DateTime.cast => try Date.cast
289
+ end
290
+ ```
291
+
292
+ - namespaced type errors:
293
+
294
+ ```ruby
295
+ # before:
296
+ SmartCore::Types::Value::Boolean.validate!(123)
297
+ # => SmartCore::Types::TypeError
298
+ SmartCore::Types::Value::Class.cast(123)
299
+ # => SmartCore::Types::TypeCastingError
300
+
301
+ # after:
302
+ SmartCore::Types::Value::Boolean.validate!(123)
303
+ # => SmartCore::Types::Value::Boolean::TypeError
304
+ # (inheritance tree: Types::Value::<Type>::TypeError => Types::Value::TypeError => Types::TypeError)
305
+
306
+ SmartCore::Types::Value::Class.cast(123)
307
+ # => SmartCore::Types::Value::Class::TypeCastingError
308
+ # (inheritance tree: the same as above)
309
+ ```
310
+
311
+ - type refinements:
312
+
313
+ ```ruby
314
+ SmartCore::Types::Value::Time.refine_checker do |value, original_checker|
315
+ # new type checker
316
+ end
317
+
318
+ SmartCore::Types::Value::Time.refine_caster do |value, original_caster|
319
+ # new type caster
320
+ end
321
+
322
+ # .refine_invariant
323
+ # .refine_invariant_chain
324
+ ```
325
+
326
+ - options for type casters:
327
+
328
+ ```ruby
329
+ SmartCore::Types::Value.define_type(:Date) do |type|
330
+ type.define_caster do |value, options = {}| # options goes here
331
+ iso = options.fetch(:iso, nil)
332
+ iso ? ::Date.pasre(value, iso) : ::Date.parse(value)
333
+ end
334
+ end
335
+
336
+ # usage:
337
+ SmartCore::Types::Value::Date.cast('2020-01-01', { iso: :rfc3339 })
338
+ ```
339
+
340
+ - new types:
341
+
342
+ ```ruby
343
+ SmartCore::Types::Value::Method
344
+ SmartCore::Types::Value::UnboundMethod
345
+ SmartCore::Types::Value::Enumerable
346
+ SmartCore::Types::Value::Comparable
347
+ SmartCore::Types::Value::Enumerator
348
+ SmartCore::Types::Value::EnumeratorChain
349
+ SmartCore::Types::Value::Range
350
+ SmartCore::Types::Value::Rational
351
+ SmartCore::Types::Value::Set
352
+ SmartCore::Types::Value::SortedSet
353
+ SmartCore::Types::Value::IO
354
+ SmartCore::Types::Value::StringIO
355
+ SmartCore::Types::Struct::Schema
356
+ SmartCore::Types::Struct::JSONSchema
357
+ SmartCore::Types::Struct::StrictArray
358
+ SmartCore::Types::Struct::StrictHash
359
+ SmartCore::Types::Struct::Map
360
+ SmartCore::Types::Variative::Enum
361
+ SmartCore::Types::Variative::Variant
362
+ SmartCore::Types::Protocol::InstanceOf
363
+ SmartCore::Types::Protocol::Interface
364
+ SmartCore::Types::Protocol::Ancestors
365
+ SmartCore::Types::Protocol::Enumerable
366
+ SmartCore::Types::Protocol::Comparable
367
+ SmartCore::Types::Protocol::Forwardable
368
+ SmartCore::Types::Protocol::Callable
369
+ ```
370
+
371
+ - support for type of empty non-defined type (`SmartCore::Types::Primitive::Undefined`);
372
+ - constrained types;
373
+ - moudle-based type system integration;
374
+ - constructor implementation and support;
375
+ - support for invariant checking (and custom definitioning) in sum-types;
376
+ - to provide a type comparability and compatability between all passed types
377
+ you should provide `type.reconcilable { |value, *types| .... }` setting;
378
+ - `type.reconcilable` should be accesible for type sum and type mult definitions;
379
+ - (**preliminarily**) invariants of the concrete passed type should be valid for sucessful invariant check;
380
+ - support for invariant checking (and definitioning) in mult-types;
381
+ - to provide a type comparability and compatability between all passed types
382
+ you should provide `type.reconcilable { |value, *types| .... }` setting;
383
+ - `type.reconcilable` should be accesible for type sum and type mult definitions;
384
+ - (**preliminarily**) all invariants of all types should be valid for sucessful invariant check;
115
385
 
116
386
  ## Contributing
117
387