nrser 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
  3. data/lib/nrser/char.rb +0 -6
  4. data/lib/nrser/core_ext/array.rb +120 -0
  5. data/lib/nrser/core_ext/binding.rb +44 -0
  6. data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
  7. data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
  8. data/lib/nrser/core_ext/exception.rb +30 -0
  9. data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
  10. data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
  11. data/lib/nrser/core_ext/hash.rb +50 -0
  12. data/lib/nrser/core_ext/module/method_objects.rb +96 -0
  13. data/lib/nrser/core_ext/module/names.rb +69 -0
  14. data/lib/nrser/core_ext/module/source_locations.rb +214 -0
  15. data/lib/nrser/core_ext/module.rb +2 -0
  16. data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
  17. data/lib/nrser/core_ext/object.rb +46 -0
  18. data/lib/nrser/core_ext/open_struct.rb +6 -0
  19. data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
  20. data/lib/nrser/{ext → core_ext}/string.rb +6 -12
  21. data/lib/nrser/core_ext/symbol.rb +13 -0
  22. data/lib/nrser/core_ext/time.rb +46 -0
  23. data/lib/nrser/core_ext.rb +13 -0
  24. data/lib/nrser/errors/abstract_method_error.rb +150 -0
  25. data/lib/nrser/errors/argument_error.rb +42 -0
  26. data/lib/nrser/errors/nicer_error.rb +298 -72
  27. data/lib/nrser/errors/type_error.rb +46 -0
  28. data/lib/nrser/errors.rb +4 -53
  29. data/lib/nrser/ext/tree.rb +3 -0
  30. data/lib/nrser/functions/enumerable/associate.rb +6 -9
  31. data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
  32. data/lib/nrser/functions/enumerable.rb +1 -3
  33. data/lib/nrser/functions/exception.rb +1 -1
  34. data/lib/nrser/functions/hash.rb +0 -6
  35. data/lib/nrser/functions/merge_by.rb +2 -2
  36. data/lib/nrser/functions/module/method_objects.rb +77 -0
  37. data/lib/nrser/functions/module.rb +1 -2
  38. data/lib/nrser/functions/open_struct.rb +25 -35
  39. data/lib/nrser/functions/proc.rb +1 -6
  40. data/lib/nrser/functions/string/looks_like.rb +32 -1
  41. data/lib/nrser/functions/string.rb +1 -40
  42. data/lib/nrser/functions/text/lines.rb +2 -1
  43. data/lib/nrser/functions.rb +0 -1
  44. data/lib/nrser/graph/tsorter.rb +41 -0
  45. data/lib/nrser/labs/core_ext/binding.rb +37 -0
  46. data/lib/nrser/labs/stash.rb +372 -0
  47. data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
  48. data/lib/nrser/log/appender.rb +3 -0
  49. data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
  50. data/lib/nrser/log/formatters/mixin.rb +270 -0
  51. data/lib/nrser/{logging → log}/formatters.rb +0 -0
  52. data/lib/nrser/log/logger.rb +229 -0
  53. data/lib/nrser/log/mixin.rb +56 -0
  54. data/lib/nrser/log.rb +723 -0
  55. data/lib/nrser/message.rb +24 -3
  56. data/lib/nrser/meta/source/location.rb +158 -0
  57. data/lib/nrser/meta.rb +1 -1
  58. data/lib/nrser/props/class_methods.rb +118 -0
  59. data/lib/nrser/props/immutable/hash.rb +111 -0
  60. data/lib/nrser/props/immutable/hash_variable.rb +82 -0
  61. data/lib/nrser/props/immutable/instance_variables.rb +48 -0
  62. data/lib/nrser/props/immutable/vector.rb +107 -0
  63. data/lib/nrser/props/instance_methods.rb +184 -0
  64. data/lib/nrser/props/metadata.rb +359 -0
  65. data/lib/nrser/props/mutable/instance_variables.rb +60 -0
  66. data/lib/nrser/props/mutable/stash.rb +199 -0
  67. data/lib/nrser/{meta/props → props}/prop.rb +217 -112
  68. data/lib/nrser/props/storage/instance_variable.rb +85 -0
  69. data/lib/nrser/props/storage/instance_variables.rb +67 -0
  70. data/lib/nrser/props/storage/key.rb +88 -0
  71. data/lib/nrser/props.rb +9 -0
  72. data/lib/nrser/refinements/sugar.rb +41 -0
  73. data/lib/nrser/refinements/types.rb +2 -2
  74. data/lib/nrser/refinements.rb +14 -16
  75. data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
  76. data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
  77. data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
  78. data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
  79. data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
  80. data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
  81. data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
  82. data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
  83. data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
  84. data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
  85. data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
  86. data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
  87. data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
  88. data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
  89. data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
  90. data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
  91. data/lib/nrser/rspex/example_group/overrides.rb +66 -0
  92. data/lib/nrser/rspex/example_group.rb +20 -252
  93. data/lib/nrser/rspex/format.rb +83 -17
  94. data/lib/nrser/rspex.rb +4 -34
  95. data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
  96. data/lib/nrser/{env → sys/env}/path.rb +1 -2
  97. data/lib/nrser/{env.rb → sys/env.rb} +2 -1
  98. data/lib/nrser/sys.rb +5 -0
  99. data/lib/nrser/types/any.rb +36 -7
  100. data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
  101. data/lib/nrser/types/attrs.rb +68 -15
  102. data/lib/nrser/types/booleans.rb +95 -34
  103. data/lib/nrser/types/bounded.rb +12 -10
  104. data/lib/nrser/types/combinators.rb +74 -37
  105. data/lib/nrser/types/errors/check_error.rb +86 -0
  106. data/lib/nrser/types/errors/from_string_error.rb +82 -0
  107. data/lib/nrser/types/factory.rb +91 -0
  108. data/lib/nrser/types/hashes.rb +171 -26
  109. data/lib/nrser/types/in.rb +25 -12
  110. data/lib/nrser/types/is.rb +50 -18
  111. data/lib/nrser/types/is_a.rb +52 -33
  112. data/lib/nrser/types/labels.rb +6 -33
  113. data/lib/nrser/types/maybe.rb +12 -4
  114. data/lib/nrser/types/nil.rb +24 -4
  115. data/lib/nrser/types/not.rb +6 -16
  116. data/lib/nrser/types/numbers.rb +94 -57
  117. data/lib/nrser/types/pairs.rb +57 -57
  118. data/lib/nrser/types/paths.rb +112 -133
  119. data/lib/nrser/types/responds.rb +64 -74
  120. data/lib/nrser/types/shape.rb +29 -24
  121. data/lib/nrser/types/strings.rb +25 -17
  122. data/lib/nrser/types/symbols.rb +19 -17
  123. data/lib/nrser/types/trees.rb +18 -70
  124. data/lib/nrser/types/tuples.rb +36 -40
  125. data/lib/nrser/types/type.rb +342 -91
  126. data/lib/nrser/types/when.rb +40 -18
  127. data/lib/nrser/types/where.rb +94 -9
  128. data/lib/nrser/types.rb +72 -63
  129. data/lib/nrser/version.rb +1 -1
  130. data/lib/nrser.rb +18 -18
  131. data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
  132. data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
  133. data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
  134. data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
  135. data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
  136. data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
  137. data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
  138. data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
  139. data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
  140. data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
  141. data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
  142. data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
  143. data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
  144. data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
  145. data/spec/lib/nrser/refinements/array_spec.rb +2 -15
  146. data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
  147. data/spec/lib/nrser/refinements/set_spec.rb +2 -15
  148. data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
  149. data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
  150. data/spec/lib/nrser/types/array_spec.rb +8 -8
  151. data/spec/lib/nrser/types/paths_spec.rb +15 -18
  152. data/spec/spec_helper.rb +4 -0
  153. metadata +109 -69
  154. data/lib/nrser/ext/binding.rb +0 -36
  155. data/lib/nrser/ext/module.rb +0 -62
  156. data/lib/nrser/ext.rb +0 -8
  157. data/lib/nrser/functions/binding.rb +0 -76
  158. data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
  159. data/lib/nrser/functions/enumerable/map_values.rb +0 -94
  160. data/lib/nrser/functions/hash/deep_merge.rb +0 -57
  161. data/lib/nrser/functions/hash/except_keys.rb +0 -44
  162. data/lib/nrser/functions/hash/slice_keys.rb +0 -43
  163. data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
  164. data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
  165. data/lib/nrser/functions/hash/transform_keys.rb +0 -140
  166. data/lib/nrser/functions/module/methods.rb +0 -206
  167. data/lib/nrser/functions/module/source_locations.rb +0 -213
  168. data/lib/nrser/logging/appender.rb +0 -3
  169. data/lib/nrser/logging.rb +0 -353
  170. data/lib/nrser/meta/props/base.rb +0 -31
  171. data/lib/nrser/meta/props.rb +0 -357
  172. data/lib/nrser/refinements/array.rb +0 -133
  173. data/lib/nrser/refinements/binding.rb +0 -6
  174. data/lib/nrser/refinements/enumerator.rb +0 -5
  175. data/lib/nrser/refinements/exception.rb +0 -35
  176. data/lib/nrser/refinements/hash.rb +0 -150
  177. data/lib/nrser/refinements/module.rb +0 -5
  178. data/lib/nrser/refinements/object.rb +0 -42
  179. data/lib/nrser/refinements/open_struct.rb +0 -28
  180. data/lib/nrser/refinements/pathname.rb +0 -5
  181. data/lib/nrser/refinements/set.rb +0 -5
  182. data/lib/nrser/refinements/string.rb +0 -5
  183. data/lib/nrser/refinements/symbol.rb +0 -20
  184. data/lib/nrser/rspex/described.rb +0 -99
  185. data/spec/design/mapping_spec.rb +0 -42
  186. data/spec/lib/nrser/functions/hash_spec.rb +0 -41
  187. data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
  188. data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -3,73 +3,92 @@ require 'nrser/types/type'
3
3
  using NRSER
4
4
 
5
5
  module NRSER::Types
6
+ # Type satisfied by class membership (or mixin presence for modules).
7
+ #
8
+ # Tests via the subject value's `#is_a?` method.
9
+ #
6
10
  class IsA < NRSER::Types::Type
7
- attr_reader :klass
8
-
9
- def initialize klass, **options
10
- unless klass.is_a?( Class ) || klass.is_a?( Module )
11
- raise ArgumentError.new binding.erb <<-ERB
12
- `klass` argument must be a Class or Module, found:
13
-
14
- <%= klass.pretty_inspect %>
15
-
16
- ERB
11
+ attr_reader :mod
12
+
13
+ def initialize mod, init_from_data: false, **options
14
+ unless mod.is_a?( Module )
15
+ raise ArgumentError,
16
+ "`mod` argument must be a Module (inc. Class), " \
17
+ "received #{ mod.inspect }"
17
18
  end
18
19
 
19
20
  super **options
20
- @klass = klass
21
+
22
+ @init_from_data = !!init_from_data
23
+
24
+ @mod = mod
21
25
  end
22
26
 
23
27
 
24
- def default_name
25
- @klass.name
28
+ def explain
29
+ mod.safe_name
26
30
  end
27
31
 
28
32
 
29
- def test value
30
- value.is_a? @klass
33
+ def test? value
34
+ value.is_a? mod
31
35
  end
32
36
 
33
37
 
34
- # If {#klass} responds to `#from_data`, call that and check results.
38
+
39
+ # @todo Document init_from_data? method.
40
+ #
41
+ # @param [type] arg_name
42
+ # @todo Add name param description.
35
43
  #
36
- # Otherwise, forward up to {NRSER::Types::Type#from_data}.
44
+ # @return [return_type]
45
+ # @todo Document return value.
37
46
  #
38
- # @param [Object] data
39
- # Data to create the value from that will satisfy the type.
47
+ def init_from_data?
48
+ @init_from_data
49
+ end # #init_from_data?
50
+
51
+
52
+
53
+ # Forwards to `mod.from_data`.
40
54
  #
41
- # @return [Object]
42
- # Instance of {#klass}.
55
+ # @param data (see NRSER::Types::Type#from_data)
56
+ # @return (see NRSER::Types::Type#from_data)
57
+ # @raise (see NRSER::Types::Type#from_data)
43
58
  #
44
- def from_data data
45
- if @from_data.nil?
46
- if @klass.respond_to? :from_data
47
- check @klass.from_data( data )
48
- else
49
- super data
50
- end
59
+ def custom_from_data data
60
+ if init_from_data?
61
+ mod.new data
51
62
  else
52
- @from_data.call data
63
+ mod.from_data data
53
64
  end
54
65
  end
55
66
 
56
67
 
68
+ # Overrides {NRSER::Types::Type#has_from_data?} to respond `true` when
69
+ # there is a instance-specific `@from_data` or the {#mod} responds to
70
+ # `.from_data`.
71
+ #
72
+ # @return [Boolean]
73
+ #
57
74
  def has_from_data?
58
- @from_data || @klass.respond_to?( :from_data )
75
+ @from_data ||
76
+ init_from_data? ||
77
+ mod.respond_to?( :from_data )
59
78
  end
60
79
 
61
80
 
62
81
  def == other
63
82
  equal?( other ) ||
64
83
  ( self.class == other.class &&
65
- self.klass == other.klass )
84
+ self.mod == other.mod )
66
85
  end
67
86
 
68
87
  end # IsA
69
88
 
70
89
 
71
90
  # class membership
72
- def self.is_a klass, **options
73
- IsA.new klass, **options
91
+ def_factory :is_a do |mod, **options|
92
+ IsA.new mod, **options
74
93
  end
75
94
  end # NRSER::Types
@@ -1,28 +1,5 @@
1
- # Requirements
2
- # =======================================================================
3
-
4
- # Stdlib
5
- # -----------------------------------------------------------------------
6
-
7
- # Deps
8
- # -----------------------------------------------------------------------
9
-
10
- # Project / Package
11
- # -----------------------------------------------------------------------
12
-
13
-
14
- # Refinements
15
- # =======================================================================
16
-
17
- require 'nrser/refinements'
18
- using NRSER
19
-
20
-
21
- # Declarations
22
- # =======================================================================
23
-
24
- module NRSER; end
25
-
1
+ require_relative './combinators'
2
+ require_relative './strings'
26
3
 
27
4
  # Definitions
28
5
  # =======================================================================
@@ -36,14 +13,10 @@ module NRSER::Types
36
13
  #
37
14
  # @return [NRSER::Types::Type]
38
15
  #
39
- def self.label **options
40
- if options.empty?
41
- LABEL
42
- else
43
- union non_empty_str, non_empty_sym, **options
44
- end
16
+ def_factory(
17
+ :label,
18
+ ) do |name: 'Label', **options|
19
+ union non_empty_str, non_empty_sym, name: name, **options
45
20
  end # .label
46
21
 
47
- LABEL = label( name: 'LabelType' ).freeze
48
-
49
22
  end # module NRSER::Types
@@ -1,10 +1,18 @@
1
- require 'nrser/types/combinators'
1
+ require_relative './combinators'
2
+ require_relative './nil'
2
3
 
3
4
  module NRSER::Types
4
5
 
5
- # nil or the argument type
6
- def self.maybe type, **options
7
- union self.nil, type, name: "#{ type.name }?", **options
6
+ # Type satisfied by `nil` or the parametrized type.
7
+ #
8
+ def_factory(
9
+ :maybe,
10
+ ) do |type, **options|
11
+ union \
12
+ self.nil,
13
+ type,
14
+ name: (options[:name] || "#{ type.name }?"),
15
+ **options
8
16
  end
9
17
 
10
18
  end # NRSER::Types
@@ -1,8 +1,28 @@
1
- require 'nrser/types/is'
1
+ require_relative './is'
2
2
 
3
3
  module NRSER::Types
4
- # nothing
5
- def self.nil
6
- is nil, name: 'Nil'
4
+ # Type for `nil`, itself and only.
5
+ #
6
+ # @todo
7
+ # Should we have a `#from_s` that converts the empty string to `nil`?
8
+ #
9
+ # Kind-of seems like we would want that to be a different types so that
10
+ # you can have a Nil type that is distinct from the empty string in
11
+ # parsing, but also have a type that accepts the empty string and coverts
12
+ # it to `nil`?
13
+ #
14
+ # Something like:
15
+ #
16
+ # type = t.empty | t.non_empty_str
17
+ # type.from_s ''
18
+ # # => nil
19
+ # type.from_s 'blah'
20
+ # # => 'blah'
21
+ #
22
+ def_factory(
23
+ :nil,
24
+ aliases: [ :null ],
25
+ ) do |name: 'Nil', **options|
26
+ is nil, name: name, **options
7
27
  end
8
28
  end # NRSER::Types
@@ -22,31 +22,21 @@ module NRSER::Types
22
22
  # Instance Methods
23
23
  # ======================================================================
24
24
 
25
- def test value
25
+ def test? value
26
26
  ! @type.test( value )
27
27
  end
28
28
 
29
29
 
30
- def default_name
31
- "!#{ @type.name }"
30
+ def explain
31
+ "~#{ @type.name }"
32
32
  end
33
33
 
34
-
35
- # @return [String]
36
- # a brief string description of the type - just it's {#name} surrounded
37
- # by some back-ticks to make it easy to see where it starts and stops.
38
- #
39
- def to_s
40
- "{ x ∉ #{ @type.name } }"
41
- end
42
-
43
- alias_method :inspect, :to_s
44
-
45
-
46
34
  end # class Not
47
35
 
48
36
 
49
- def self.not type, **options
37
+ def_factory(
38
+ :not,
39
+ ) do |type, **options|
50
40
  Not.new type, **options
51
41
  end
52
42
 
@@ -15,8 +15,8 @@ module NRSER::Types
15
15
  # @return [Float]
16
16
  # If the string represents a decimal number.
17
17
  #
18
- def self.parse_number s
19
- float = Float s
18
+ def self.parse_number string
19
+ float = Float string
20
20
  int = float.to_i
21
21
  if float == int then int else float end
22
22
  end
@@ -25,48 +25,44 @@ module NRSER::Types
25
25
  # Zero
26
26
  # =====================================================================
27
27
 
28
- ZERO = is(
29
- 0,
30
- name: 'ZeroType',
31
- from_s: method( :parse_number )
32
- ).freeze
33
-
34
- def self.zero
35
- ZERO
28
+ def_factory(
29
+ :Zero,
30
+ aliases: [ :zero ],
31
+ ) do |from_s: method( :parse_number ), **options|
32
+ is \
33
+ 0,
34
+ from_s: from_s,
35
+ **options
36
36
  end
37
37
 
38
38
 
39
39
  # Number ({Numeric})
40
40
  # =====================================================================
41
41
 
42
- NUM = IsA.new(
43
- Numeric,
44
- name: 'NumType',
45
- from_s: method( :parse_number )
46
- ).freeze
47
-
48
- def self.num
49
- NUM
42
+ def_factory(
43
+ :Number,
44
+ aliases: [ :num, :number, :numeric, :Numeric ],
45
+ ) do |name: 'Number', from_s: method( :parse_number ), **options|
46
+ IsA.new \
47
+ Numeric,
48
+ from_s: from_s,
49
+ **options
50
50
  end
51
51
 
52
- singleton_class.send :alias_method, :number, :num
53
-
54
52
 
55
53
  # Integers
56
54
  # =====================================================================
57
55
 
58
- INT = IsA.new(
59
- Integer,
60
- name: 'IntType',
61
- from_s: method( :parse_number )
62
- ).freeze
63
-
64
- def self.int
65
- INT
56
+ def_factory(
57
+ :Integer,
58
+ aliases: [ :int, :integer, :signed ],
59
+ ) do |name: 'ℤ', from_s: method( :parse_number ), **options|
60
+ IsA.new \
61
+ Integer,
62
+ from_s: from_s,
63
+ **options
66
64
  end
67
65
 
68
- singleton_class.send :alias_method, :integer, :int
69
-
70
66
 
71
67
  # Bounded Integers
72
68
  # ---------------------------------------------------------------------
@@ -77,12 +73,15 @@ module NRSER::Types
77
73
  # Integer greater than zero.
78
74
  #
79
75
 
80
- def self.pos_int
81
- intersection(
82
- INT,
83
- bounded(min: 1),
84
- name: 'ℤ⁺'
85
- ).freeze
76
+ def_factory(
77
+ :PositiveInteger,
78
+ aliases: [ :pos_int, :positive_int, :positive_integer ]
79
+ ) do |name: 'ℤ⁺', **options|
80
+ intersection \
81
+ int,
82
+ bounded( min: 1 ),
83
+ name: name,
84
+ **options
86
85
  end
87
86
 
88
87
  # Ugh sometimes the naturals have 0, so omit it...
@@ -95,12 +94,15 @@ module NRSER::Types
95
94
  # Integer less than zero.
96
95
  #
97
96
 
98
- def self.neg_int
99
- intersection(
100
- INT,
101
- bounded(max: -1),
102
- name: 'ℤ⁻'
103
- ).freeze
97
+ def_factory(
98
+ :NegativeInteger,
99
+ aliases: [ :neg_int, :negative_int, :negative_integer ],
100
+ ) do |name: 'ℤ⁻', **options|
101
+ intersection \
102
+ int,
103
+ bounded( max: -1 ),
104
+ name: name,
105
+ **options
104
106
  end
105
107
 
106
108
 
@@ -111,20 +113,23 @@ module NRSER::Types
111
113
  # as bounded instead of a union.
112
114
  #
113
115
 
114
- def self.non_neg_int **options
115
- # Alternative symbol: 'ℤ⋆'
116
- intersection INT, bounded(min: 0), name: '{0}∪ℤ⁺', **options
117
- end
118
-
119
- singleton_class.send :alias_method, :unsigned, :non_neg_int
120
-
121
-
122
- def self.non_neg_int? **options
123
- maybe non_neg_int, **options
116
+ def_factory(
117
+ :NonNegativeInteger,
118
+ aliases: [
119
+ :non_neg_int,
120
+ :unsigned,
121
+ :index,
122
+ :non_negative_int,
123
+ :non_negative_integer,
124
+ ],
125
+ ) do |name: 'ℕ⁰', **options|
126
+ intersection \
127
+ int,
128
+ bounded( min: 0 ),
129
+ name: name,
130
+ **options
124
131
  end
125
132
 
126
- singleton_class.send :alias_method, :unsigned?, :non_neg_int?
127
-
128
133
 
129
134
  # Non-Positive Integer
130
135
  # --------------------
@@ -132,8 +137,40 @@ module NRSER::Types
132
137
  # negative integers and zero.
133
138
  #
134
139
 
135
- def self.non_pos_int **options
136
- intersection INT, bounded(max: 0), name: '{0}∪ℤ⁻', **options
140
+ def_factory(
141
+ :NonPositiveInteger,
142
+ aliases: [ :non_pos_int, :non_positive_int, :non_positive_integer ],
143
+ ) do |name: '{0}∪ℤ⁻', **options|
144
+ intersection \
145
+ int,
146
+ bounded( max: 0 ),
147
+ name: name,
148
+ **options
149
+ end
150
+
151
+
152
+ def_factory(
153
+ :Unsigned16BitInteger,
154
+ aliases: [ :uint16, :ushort ],
155
+ ) do |name: 'uint16', **options|
156
+ intersection \
157
+ int,
158
+ bounded( min: 0, max: ((2 ** 16) - 1) ),
159
+ name: name,
160
+ **options
137
161
  end
138
-
162
+
163
+
164
+ # TODO Move?
165
+ def_factory(
166
+ :UNIXPort,
167
+ aliases: [ :port, ],
168
+ ) do |name: 'port', **options|
169
+ intersection \
170
+ int,
171
+ bounded( min: 1, max: (2**16 - 1) ),
172
+ name: name,
173
+ **options
174
+ end
175
+
139
176
  end # NRSER::Types
@@ -9,7 +9,10 @@
9
9
 
10
10
  # Project / Package
11
11
  # -----------------------------------------------------------------------
12
+ require 'nrser/core_ext/hash'
13
+
12
14
  require_relative './combinators'
15
+ require_relative './tuples'
13
16
 
14
17
 
15
18
  # Refinements
@@ -27,83 +30,80 @@ module NRSER; end
27
30
 
28
31
  module NRSER::Types
29
32
 
30
-
31
- # @todo Document array_pair method.
32
- #
33
- # @param [type] arg_name
34
- # @todo Add name param description.
33
+ # Type for key/value pairs encoded as a {.tuple} (Array) of length 2.
35
34
  #
36
- # @return [return_type]
37
- # @todo Document return value.
38
- #
39
- def self.array_pair **options
40
- return ARRAY_PAIR if options.empty?
41
-
42
- key = options.delete(:key) || ANY
43
- value = options.delete(:value) || ANY
35
+ def_factory(
36
+ :array_pair,
37
+ ) do |name: 'ArrayPair', key: any, value: any, **options|
38
+ unless options.key? :name
39
+ options[:name] = if key == any && value == any
40
+ 'ArrayPair'
41
+ else
42
+ key = NRSER::Types.make key
43
+ value = NRSER::Types.make value
44
+
45
+ "ArrayPair<#{ key.name }, #{ value.name }>"
46
+ end
47
+ end
44
48
 
45
- tuple key, value, **options
49
+ tuple \
50
+ key,
51
+ value,
52
+ # name: name,
53
+ **options
46
54
  end # .array_pair
47
55
 
48
- ARRAY_PAIR = array_pair( name: 'ArrayPairType' ).freeze
49
56
 
50
-
51
- # Type for a {Hash} that consists of only a single key and value pair.
57
+ # Type for key/value pairs encoded as {Hash} with a single entry.
52
58
  #
53
59
  # @param [String] name:
54
60
  # Name to give the new type.
55
61
  #
56
62
  # @param [Hash] **options
57
- # Other options to pass to
58
- #
59
- # @return [NRSER::Types::Type]
63
+ # Other options to pass to
60
64
  #
61
- def self.hash_pair **options
62
- return HASH_PAIR if options.empty?
63
-
64
- hash_options = {}
65
- {key: :keys, value: :values}.each { |from_key, to_key|
66
- if options.key? from_key
67
- hash_options[to_key] = options.delete from_key
65
+ def_factory(
66
+ :hash_pair,
67
+ ) do |key: any, value: any, **options|
68
+ unless options.key? :name
69
+ options[:name] = if key == any && value == any
70
+ 'HashPair'
71
+ else
72
+ key = NRSER::Types.make key
73
+ value = NRSER::Types.make value
74
+
75
+ "HashPair<#{ key.name }, #{ value.name }>"
68
76
  end
69
- }
70
-
71
- if hash_options.empty?
72
- intersection is_a( Hash ), length( 1 ), **options
73
- else
74
- intersection \
75
- hash_type( **hash_options ),
76
- length( 1 ),
77
- **options
78
77
  end
79
78
 
79
+ intersection \
80
+ hash_type( keys: key, values: value ),
81
+ length( 1 ),
82
+ # name: name,
83
+ **options
80
84
  end # .hash_pair
81
85
 
82
- HASH_PAIR = hash_pair( name: 'HashPairType' ).freeze
83
-
84
86
 
85
- # @todo Document pair method.
86
- #
87
- # @param [type] arg_name
88
- # @todo Add name param description.
87
+ # A key/value pair, which can be encoded as an Array of length 2 or a
88
+ # Hash of length 1.
89
89
  #
90
- # @return [return_type]
91
- # @todo Document return value.
92
90
  #
93
- def self.pair **options
94
- if options.empty?
95
- PAIR
96
- else
97
- type_options = NRSER.slice_keys! options, :key, :value
98
-
99
- union \
100
- array_pair( **type_options ),
101
- hash_pair( **type_options ),
102
- **options
91
+ def_factory :pair do |key: any, value: any, **options|
92
+ unless options.key? :name
93
+ options[:name] = if key == any && value == any
94
+ 'Pair'
95
+ else
96
+ key = NRSER::Types.make key
97
+ value = NRSER::Types.make value
98
+
99
+ "Pair<#{ key.name }, #{ value.name }>"
100
+ end
103
101
  end
102
+
103
+ union \
104
+ array_pair( key: key, value: value ),
105
+ hash_pair( key: key, value: value ),
106
+ **options
104
107
  end # #pair
105
108
 
106
- PAIR = pair( name: 'PairType' ).freeze
107
-
108
109
  end # module NRSER::Types
109
-