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
data/lib/nrser/message.rb CHANGED
@@ -52,7 +52,7 @@ module NRSER
52
52
 
53
53
  # Name of method the message is for.
54
54
  #
55
- # @return [Symbol | String]
55
+ # @return [Symbol]
56
56
  #
57
57
  attr_reader :symbol
58
58
 
@@ -83,12 +83,33 @@ module NRSER
83
83
  # Optional block that should be sent.
84
84
  #
85
85
  def initialize symbol, *args, &block
86
- @symbol = symbol
86
+ @symbol = symbol.to_sym
87
87
  @args = args
88
88
  @block = block
89
89
  end
90
90
 
91
91
 
92
+ def options
93
+ if args.last.is_a? Hash
94
+ args.last
95
+ else
96
+ {}
97
+ end
98
+ end
99
+
100
+
101
+ def symbolize_options
102
+ if args.last.is_a? Hash
103
+ self.class.new \
104
+ symbol,
105
+ *args[0..-2],
106
+ args.last.sym_keys
107
+ else
108
+ self
109
+ end
110
+ end
111
+
112
+
92
113
  # Creates a {Proc} that accepts a single `receiver` argument and calls
93
114
  # {#sent_to} on it, allowing messages to be used via the `&` operator
94
115
  # in `map`, etc.
@@ -114,7 +135,7 @@ module NRSER
114
135
  end
115
136
 
116
137
  alias_method :to_sender, :to_proc
117
-
138
+
118
139
 
119
140
  # Send this instance to a receiver object.
120
141
  #
@@ -0,0 +1,158 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Deps
11
+ # -----------------------------------------------------------------------
12
+
13
+ # Project / Package
14
+ # -----------------------------------------------------------------------
15
+
16
+ require 'nrser/props'
17
+ require 'nrser/props/immutable/vector'
18
+
19
+
20
+ # Refinements
21
+ # =======================================================================
22
+
23
+ using NRSER::Types
24
+
25
+
26
+ # Declarations
27
+ # =======================================================================
28
+
29
+ module NRSER::Meta::Source; end
30
+
31
+
32
+ # Definitions
33
+ # =======================================================================
34
+
35
+ # @todo document NRSER::Meta::Source::Location class.
36
+ #
37
+ class NRSER::Meta::Source::Location < Hamster::Vector
38
+
39
+ # Mixins
40
+ # ============================================================================
41
+
42
+ include NRSER::Props::Immutable::Vector
43
+
44
+
45
+ # Class Methods
46
+ # ============================================================================
47
+
48
+ # Given an {Enumerable} of {Method} objects, return a {Hash} mapping their
49
+ # {Method#name} to the method's {NRSER::Meta::Source::Location}.
50
+ #
51
+ # @note
52
+ # We map the names instead of the {Method} objects themselves because
53
+ # aliases produce two different {Method} objects that `#==` and `#hash`
54
+ # the same, preventing them both from being {Hash} keys.
55
+ #
56
+ # @param [Enumerable<Method>] methods
57
+ # Methods you want the source locations for.
58
+ #
59
+ # @param [Boolean] only_valid:
60
+ # When `true` filter the results to only those that are {#valid?}.
61
+ #
62
+ # @return [Hash<Symbol, NRSER::Meta::Source::Location>]
63
+ # Map of method name to their source locations.
64
+ #
65
+ def self.for_methods methods, only_valid: false
66
+ all = methods.map { |method|
67
+ [ method.name, NRSER::Meta::Source::Location.new( method ) ]
68
+ }.to_h
69
+
70
+ if only_valid
71
+ all.select { |method, location| location.valid? }
72
+ else
73
+ all
74
+ end
75
+ end # .for_methods
76
+
77
+
78
+ # Props
79
+ # ======================================================================
80
+
81
+ prop :file, type: t.abs_path?, default: nil, index: 0
82
+ prop :line, type: t.pos_int?, default: nil, index: 1
83
+
84
+
85
+ # Constructor
86
+ # ============================================================================
87
+
88
+ # Override to allow argument to be `nil` for when {Method#source_location}
89
+ # weirdly returns `nil`.
90
+ #
91
+ # @param [(#[] & (#each_pair | #each_index)) | nil ] source
92
+ # Source to construct from:
93
+ #
94
+ # 1. `#[] & (#each_pair | #each_index)`
95
+ # 1. Hash-like that responds to `#each_pair` and contains prop
96
+ # value sources keyed by their names.
97
+ #
98
+ # Supports standard propertied class construction.
99
+ #
100
+ # **Examples:**
101
+ #
102
+ # {file: '/some/abs/path.rb', line: 88}
103
+ # {file: '/some/abs/path.rb', line: nil}
104
+ # {file: nil, line: 88}
105
+ # {file: nil, line: nil}
106
+ # {}
107
+ #
108
+ # 2. Array-like that responds to `#each_index` and contains prop
109
+ # values sources indexed by their non-negative integer indexes.
110
+ #
111
+ # Supports the output of {Method#source_location}.
112
+ #
113
+ # **Examples:**
114
+ #
115
+ # ['/some/abs/path.rb', 88]
116
+ # ['/some/abs/path.rb', nil]
117
+ # [nil, 88]
118
+ # [nil, nil]
119
+ # []
120
+ #
121
+ # 2. `nil` - Swapped for `{]` to support times I'm pretty sure I've seen
122
+ # {Method#source_location} return strait-up `nil`.
123
+ #
124
+ #
125
+ def initialize source
126
+ source = source.source_location if source.respond_to? :source_location
127
+ source = {} if source.nil?
128
+ super source
129
+ end
130
+
131
+
132
+ # Instance Methods
133
+ # ======================================================================
134
+
135
+ # Do we have a file and a line?
136
+ #
137
+ # Sometimes `#source_location` gives back `nil` values or just `nil`
138
+ # (in which case we set both {#file} and {#line} to `nil`). I think this
139
+ # has to do with C extensions and other weirdness.
140
+ #
141
+ # Anyways, this helps you handle it.
142
+ #
143
+ # @return [Boolean]
144
+ #
145
+ def valid?
146
+ !( file.nil? && line.nil? )
147
+ end # #valid?
148
+
149
+
150
+ # @return [String]
151
+ # a short string describing the instance.
152
+ #
153
+ def to_s
154
+ "#{ file || '???' }:#{ line || '???' }"
155
+ end # #to_s
156
+
157
+
158
+ end # class NRSER::Meta::Source::Location
data/lib/nrser/meta.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module NRSER::Meta; end
2
2
 
3
3
  require_relative './meta/class_attrs'
4
- require_relative './meta/props'
4
+ require_relative './meta/source/location'
@@ -0,0 +1,118 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Deps
11
+ # -----------------------------------------------------------------------
12
+
13
+ # Project / Package
14
+ # -----------------------------------------------------------------------
15
+ require_relative './metadata'
16
+
17
+ # Refinements
18
+ # =======================================================================
19
+
20
+
21
+ # Declarations
22
+ # =======================================================================
23
+
24
+ module NRSER::Props; end
25
+
26
+
27
+ # Definitions
28
+ # =======================================================================
29
+
30
+
31
+ # Class method "macros" that are extended in to data classes, providing the
32
+ # declaration interface.
33
+ #
34
+ module NRSER::Props::ClassMethods
35
+
36
+ include NRSER::Log::Mixin
37
+
38
+ # Get the metadata object for this class, creating it if it doesn't exist.
39
+ #
40
+ # @return [NRSER::Props::Metadata]
41
+ #
42
+ def metadata
43
+ # TODO Move into {NRSER::Props::Metadata}?
44
+ #
45
+ unless NRSER::Props::Metadata.has_metadata? self
46
+ instance_variable_set \
47
+ NRSER::Props::Metadata::VARIABLE_NAME,
48
+ NRSER::Props::Metadata.new( self )
49
+ end
50
+
51
+ NRSER::Props::Metadata.metadata_for self
52
+ end
53
+
54
+
55
+ def props *args, &block
56
+ metadata.props *args, &block
57
+ end
58
+
59
+
60
+ def prop *args, &block
61
+ metadata.prop *args, &block
62
+ end
63
+
64
+
65
+ def invariants *args, &block
66
+ metadata.invariants *args, &block
67
+ end
68
+
69
+
70
+ def invariant *args, &block
71
+ metadata.invariant *args, &block
72
+ end
73
+
74
+
75
+ # Instantiate from a data hash.
76
+ #
77
+ # @todo
78
+ # This needs to be extended to handle prop'd classes nested in
79
+ # arrays and hashes... but for the moment, it is what it is.
80
+ #
81
+ # This *may* have been fixed...?
82
+ #
83
+ # @param [#each_pair] data
84
+ #
85
+ # @return [self]
86
+ #
87
+ # @raise [NRSER::ArgumentError]
88
+ # If `data` does not respond to `#each_pair`.
89
+ #
90
+ def from_data data
91
+ values = {}
92
+ props = self.props
93
+
94
+ unless data.respond_to? :each_pair
95
+ raise NRSER::ArgumentError.new \
96
+ "`data` argument must respond to `#each_pair`",
97
+ data: data,
98
+ class: self
99
+ end
100
+
101
+ data.each_pair do |data_key, data_value|
102
+ prop_key = case data_key
103
+ when Symbol
104
+ data_key
105
+ when String
106
+ data_key.to_sym
107
+ end
108
+
109
+ if prop_key &&
110
+ (prop = props[prop_key])
111
+ values[prop_key] = prop.value_from_data data_value
112
+ end
113
+ end
114
+
115
+ self.new values
116
+ end # #from_data
117
+
118
+ end # module NRSER::Props::ClassMethods
@@ -0,0 +1,111 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+ require 'hamster'
10
+
11
+ # Project / Package
12
+ # -----------------------------------------------------------------------
13
+ require_relative '../storage/key'
14
+
15
+
16
+ # Declarations
17
+ # =======================================================================
18
+
19
+ module NRSER::Props::Immutable; end
20
+
21
+
22
+ # Definitions
23
+ # =======================================================================
24
+
25
+ # Mixin for classes that extend {Hamster::Hash} and will use itself as the
26
+ # property value storage.
27
+ #
28
+ module NRSER::Props::Immutable::Hash
29
+
30
+ # Constants
31
+ # ==========================================================================
32
+
33
+ STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :name
34
+
35
+
36
+ # Module Methods
37
+ # ======================================================================
38
+
39
+ def self.included base
40
+ unless base < Hamster::Hash
41
+ raise binding.erb <<~END
42
+ This class is only for including in {Hamster::Hash} subclasses!
43
+ END
44
+ end
45
+
46
+ base.include NRSER::Props
47
+ base.metadata.storage STORAGE
48
+ base.metadata.freeze
49
+
50
+ base.extend ClassMethods
51
+ base.include InstanceMethods
52
+ end
53
+
54
+
55
+ # Mixin Methods
56
+ # ======================================================================
57
+
58
+ # Methods mixed in at the class-level.
59
+ #
60
+ module ClassMethods
61
+ # {Hamster::Hash} uses `.alloc` to quickly create derived instances
62
+ # when it knows the instance variables. We need to hook into that to
63
+ # check the prop types.
64
+ #
65
+ # @param (see Hamster::Hash.alloc)
66
+ #
67
+ # @return [Hamster::Hash]
68
+ # The new instance, which will be of the propertied subclass of
69
+ # {Hamster::Hash}.
70
+ #
71
+ # @raise [TypeError]
72
+ # If the prop values of the new vector don't satisfy the prop types.
73
+ #
74
+ def alloc *args
75
+ super( *args ).tap do |new_instance|
76
+ self.props( only_primary: true ).values.each do |prop|
77
+ prop.check! new_instance[prop.name]
78
+ end
79
+ end
80
+ end
81
+ end # module ClassMethods
82
+
83
+ module InstanceMethods
84
+ # Constructor
85
+ # ----------------------------------------------------------------------------
86
+
87
+ # Since including classes are using themselves as storage, we need to tap
88
+ # into the `#initialize` chain in order to load property values from sources
89
+ # and pass an {Array} up to the super-method to instantiate the
90
+ # {Hamster::Hash}.
91
+ #
92
+ def initialize values = {}
93
+ # Handles things like `[[:x, 1], [:y, 2]]`
94
+ values = values.to_h unless values.respond_to?( :each_pair )
95
+
96
+ super_values = {}
97
+
98
+ self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
99
+ super_values[prop.name] = value
100
+ }
101
+
102
+ super super_values
103
+
104
+ # Check additional type invariants
105
+ self.class.invariants.each do |type|
106
+ type.check self
107
+ end
108
+ end # #initialize
109
+ end
110
+
111
+ end # module NRSER::Props::Immutable::Hash
@@ -0,0 +1,82 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Stdlib
5
+ # -----------------------------------------------------------------------
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Project / Package
11
+ # -----------------------------------------------------------------------
12
+ require_relative '../storage/key'
13
+ require_relative '../storage/instance_variable'
14
+
15
+
16
+ # Declarations
17
+ # =======================================================================
18
+
19
+ module NRSER; end
20
+ module NRSER::Props; end
21
+
22
+
23
+ # Definitions
24
+ # =======================================================================
25
+
26
+ # Mix-in to store property values in an immutable {Hamster::Hash} instance
27
+ # in an instance variable.
28
+ #
29
+ # This is basically an improvement of how the original props implementation
30
+ # worked.
31
+ #
32
+ module NRSER::Props::Immutable::HashVariable
33
+
34
+ KEY_STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :name
35
+
36
+ INSTANCE_VARIABLE_STORAGE = \
37
+ NRSER::Props::Storage::InstanceVariable.new sub_storage: KEY_STORAGE
38
+
39
+
40
+ # Class Methods
41
+ # ======================================================================
42
+
43
+ def self.included base
44
+ base.include NRSER::Props
45
+ base.metadata.storage INSTANCE_VARIABLE_STORAGE
46
+ base.metadata.freeze
47
+ end
48
+
49
+
50
+ # Constructor
51
+ # ======================================================================
52
+
53
+ # Instantiate a new `NRSER::Props::Immutable::Vector`.
54
+ def initialize_props values = {}
55
+ prop_values = {}
56
+
57
+ self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
58
+ prop_values[prop.name] = value
59
+ }
60
+
61
+ instance_variable_set self.class.metadata.storage.var_name,
62
+ Hamster::Hash.new( values )
63
+
64
+ # Check additional type invariants
65
+ self.class.invariants.each do |type|
66
+ type.check self
67
+ end
68
+ end # #initialize
69
+
70
+ end # module NRSER::Props::Immutable::HashVariable
71
+
72
+
73
+ # @todo document NRSER::Props::Immutable::HashVariable::Base module.
74
+ class NRSER::Props::Immutable::HashVariable::Base
75
+
76
+ include NRSER::Props::Immutable::HashVariable
77
+
78
+ def initialize values = {}
79
+ initialize_props values
80
+ end
81
+
82
+ end # class NRSER::Props::Immutable::HashVariable::Base
@@ -0,0 +1,48 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Project / Package
5
+ # -----------------------------------------------------------------------
6
+ require_relative '../../props'
7
+ require_relative '../storage/key'
8
+ require_relative '../storage/instance_variables'
9
+
10
+
11
+ # Definitions
12
+ # =======================================================================
13
+
14
+ # Mix-in to store property values in instance variables of the same name.
15
+ #
16
+ module NRSER::Props::Immutable::InstanceVariables
17
+
18
+ STORAGE = NRSER::Props::Storage::InstanceVariables.new immutable: true
19
+
20
+
21
+ # Class Methods
22
+ # ======================================================================
23
+
24
+ def self.included base
25
+ base.include NRSER::Props
26
+ base.metadata.storage STORAGE
27
+ base.metadata.freeze
28
+ end
29
+
30
+
31
+ # Instance Methods
32
+ # ======================================================================
33
+
34
+ # Since the {NRSER::Props::Immutable::InstanceVariables} mix-in does *not*
35
+ # need to tap into the initialize chain,
36
+ #
37
+ def initialize_props values = {}
38
+ self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
39
+ instance_variable_set "@#{ prop.name }", value
40
+ }
41
+
42
+ # Check additional type invariants
43
+ self.class.invariants.each do |type|
44
+ type.check self
45
+ end
46
+ end # #initialize_props
47
+
48
+ end # module NRSER::Props::Immutable
@@ -0,0 +1,107 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+ require 'hamster'
10
+
11
+ # Project / Package
12
+ # -----------------------------------------------------------------------
13
+ require_relative '../storage/key'
14
+
15
+
16
+ # Declarations
17
+ # =======================================================================
18
+
19
+ module NRSER::Props::Immutable; end
20
+
21
+
22
+ # Definitions
23
+ # =======================================================================
24
+
25
+ # Mixin for classes that extend {Hamster::Vector} and will use itself as the
26
+ # property value storage, requiring that property keys be non-negative
27
+ # integers.
28
+ #
29
+ module NRSER::Props::Immutable::Vector
30
+
31
+ # Constants
32
+ # ==========================================================================
33
+
34
+ STORAGE = NRSER::Props::Storage::Key.new immutable: true, key_type: :index
35
+
36
+
37
+ # Module Methods
38
+ # ======================================================================
39
+
40
+ def self.included base
41
+ unless base < Hamster::Vector
42
+ raise binding.erb <<~END
43
+ This class is only for including in {Hamster::Vector} subclasses!
44
+ END
45
+ end
46
+
47
+ base.include NRSER::Props
48
+ base.metadata.storage STORAGE
49
+ base.metadata.freeze
50
+
51
+ base.extend ClassMethods
52
+ end
53
+
54
+
55
+ # Mixin Methods
56
+ # ======================================================================
57
+
58
+ # Methods mixed in at the class-level.
59
+ #
60
+ module ClassMethods
61
+ # {Hamster::Vector} uses `.alloc` to quickly create derived instances
62
+ # when it knows the instance variables. We need to hook into that to
63
+ # check the prop types.
64
+ #
65
+ # @param (see Hamster::Vector.alloc)
66
+ #
67
+ # @return [Hamster::Vector]
68
+ # The new instance, which will be of the propertied subclass of
69
+ # {Hamster::Vector}.
70
+ #
71
+ # @raise [TypeError]
72
+ # If the prop values of the new vector don't satisfy the prop types.
73
+ #
74
+ def alloc *args
75
+ super( *args ).tap do |new_instance|
76
+ self.props( only_primary: true ).each_value do |prop|
77
+ prop.check! new_instance[prop.index]
78
+ end
79
+ end
80
+ end
81
+ end # module ClassMethods
82
+
83
+
84
+ # Constructor
85
+ # ----------------------------------------------------------------------------
86
+
87
+ # Since including classes are using themselves as storage, we need to tap
88
+ # into the `#initialize` chain in order to load property values from sources
89
+ # and pass an {Array} up to the super-method to instantiate the
90
+ # {Hamster::Vector}.
91
+ #
92
+ def initialize values = {}
93
+ super_values = []
94
+
95
+ self.class.metadata.each_primary_prop_value_from( values ) { |prop, value|
96
+ super_values[prop.index] = value
97
+ }
98
+
99
+ super super_values
100
+
101
+ # Check additional type invariants
102
+ self.class.invariants.each do |type|
103
+ type.check self
104
+ end
105
+ end # #initialize
106
+
107
+ end # module NRSER::Props::Immutable::Vector