nrser 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,199 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Project / Package
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Need {NRSER::Props} to include
11
+ require_relative '../../props'
12
+
13
+ # Need {NRSER::Stash} itself
14
+ require 'nrser/labs/stash'
15
+
16
+ # Gonna use {NRSER::Props::Storage::Key} for storage
17
+ require_relative '../storage/key'
18
+
19
+
20
+ # Declarations
21
+ # =======================================================================
22
+
23
+ module NRSER::Props::Mutable; end
24
+
25
+
26
+ # Definitions
27
+ # =======================================================================
28
+
29
+ module NRSER::Props::Mutable::Stash
30
+
31
+ # Constants
32
+ # ==========================================================================
33
+
34
+ STORAGE = NRSER::Props::Storage::Key.new \
35
+ immutable: false,
36
+ key_type: :name,
37
+ get: :_raw_get,
38
+ put: :_raw_put
39
+
40
+
41
+ # Module Methods
42
+ # ======================================================================
43
+
44
+ def self.included base
45
+ unless base < NRSER::Stash
46
+ raise binding.erb <<~END
47
+ This class is only for including in {Hash} subclasses!
48
+ END
49
+ end
50
+
51
+ base.include NRSER::Props
52
+ base.include InstanceMethods
53
+ base.metadata.storage STORAGE
54
+ base.metadata.freeze
55
+ end
56
+
57
+ # Methods to be mixed in at the class-level with
58
+ # {NRSER::Props::Mutable::Hash}.
59
+ module ClassMethods
60
+
61
+ def [] *args
62
+ new ::Hash[*args]
63
+ end
64
+
65
+ end # module ClassMethods
66
+
67
+
68
+ # Instance methods to mix in with {NRSER::Props::Mutable::Hash}.
69
+ #
70
+ # We want these to *override* {NRSER::Props::InstanceMethods}, so they
71
+ # need to be separate so we can include them after {NRSER::Props} in
72
+ # {NRSER::Props::Mutable::Hash.included}.
73
+ #
74
+ module InstanceMethods
75
+
76
+ def initialize_props values = {}
77
+ # Handles things like `[[:x, 1], [:y, 2]]`, since we know that's what is
78
+ # meant in that case
79
+ values = values.to_h unless values.respond_to?( :each_pair )
80
+
81
+ self.class.metadata.
82
+ each_primary_prop_value_from( values ) { |prop, value|
83
+ _raw_put prop.name, value
84
+ }
85
+
86
+ # Check additional type invariants
87
+ self.class.invariants.each do |type|
88
+ type.check self
89
+ end
90
+
91
+ # Load in additional non-prop values, if any
92
+ #
93
+ # TODO Optimize
94
+ #
95
+
96
+ prop_names = self.class.metadata.prop_names
97
+
98
+ values.each do |key, value|
99
+ unless prop_names.include? convert_key( key )
100
+ self[key] = value
101
+ end
102
+ end
103
+ end # #initialize_props
104
+
105
+
106
+ # Override {NRSER::Props::InstanceMethods#to_data} to handle non-prop
107
+ # values in the {NRSER::Stash}.
108
+ #
109
+ # @param [Boolean] only_props:
110
+ # When `true` only prop values will be added to the data hash.
111
+ #
112
+ # Otherwise, any non-prop keys and vales will be added as well
113
+ # (default behavior).
114
+ #
115
+ # @param **kwds
116
+ # See {NRSER::Props::InstanceMethods#to_data}.
117
+ #
118
+ # @return (see NRSER::Props::InstanceMethods#to_data)
119
+ #
120
+ def to_data only_props: false, **kwds
121
+ hash = super **kwds
122
+
123
+ unless only_props
124
+ each do |key, value|
125
+ # Data uses **string** keys
126
+ key = key.to_s
127
+
128
+ # See if the key is missing
129
+ unless hash.key?( key.to_s )
130
+ # It is, so let's fill it in
131
+
132
+ # If value knows how to be data, do that
133
+ value = value.to_data if value.respond_to?( :to_data )
134
+
135
+ # Set the key/value pair
136
+ hash[key] = value
137
+ end
138
+ end
139
+ end
140
+
141
+ hash
142
+ end # #to_data
143
+
144
+
145
+ def convert_key key
146
+ case key
147
+ when Symbol
148
+ key
149
+ when String
150
+ sym = key.to_sym
151
+ if self.metadata[ sym ]
152
+ sym
153
+ else
154
+ key
155
+ end
156
+ else
157
+ key
158
+ end
159
+ end
160
+
161
+
162
+ # Store a value at a key. If the key is a prop name, store it through the
163
+ # prop, which will check it's type.
164
+ #
165
+ # @param [Symbol | String] key
166
+ # @param [VALUE] value
167
+ #
168
+ # @return [VALUE]
169
+ # The stored value.
170
+ #
171
+ def put key, value
172
+ key = convert_key key
173
+
174
+ if (prop = self.class.metadata[ key ])
175
+ prop.set self, value
176
+ else
177
+ # We know {#convert_value} is a no-op so can skip it
178
+ _raw_put key, value
179
+ end
180
+ end # #put
181
+
182
+
183
+ def dup
184
+ self.class.new( self ).tap do |new_stash|
185
+ set_defaults new_stash
186
+ end
187
+ end
188
+
189
+
190
+ # Need to patch `#merge` since {NRSER::Props::InstanceMethods} defines
191
+ # it, which overrides {NRSER::Stash#merge}, so we just put it back.
192
+ #
193
+ def merge other_hash = {}, &block
194
+ dup.update other_hash, &block
195
+ end
196
+
197
+ end # module InstanceMethods
198
+
199
+ end # module NRSER::Props::Mutable::Stash
@@ -1,7 +1,20 @@
1
+ # Requirements
2
+ # =======================================================================
3
+
4
+ # Stdlib
5
+ # -----------------------------------------------------------------------
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Project / Package
11
+ # -----------------------------------------------------------------------
12
+ require 'nrser/refinements/types'
13
+
14
+
1
15
  # Refinements
2
16
  # =======================================================================
3
17
 
4
- using NRSER
5
18
  using NRSER::Types
6
19
 
7
20
 
@@ -9,8 +22,7 @@ using NRSER::Types
9
22
  # =======================================================================
10
23
 
11
24
  module NRSER; end
12
- module NRSER::Meta; end
13
- module NRSER::Meta::Props; end
25
+ module NRSER::Props; end
14
26
 
15
27
 
16
28
  # Definitions
@@ -21,7 +33,9 @@ module NRSER::Meta::Props; end
21
33
  #
22
34
  # Props are immutable by design.
23
35
  #
24
- class NRSER::Meta::Props::Prop
36
+ class NRSER::Props::Prop
37
+
38
+ include NRSER::Log::Mixin
25
39
 
26
40
  # The class the prop was defined in.
27
41
  #
@@ -38,13 +52,27 @@ class NRSER::Meta::Props::Prop
38
52
  attr_reader :name
39
53
 
40
54
 
55
+ # The key under which the value will be stored in the storage.
56
+ #
57
+ # @return [nil | Integer]
58
+ #
59
+ attr_reader :index
60
+
61
+
41
62
  # The type of the valid values for the property.
42
63
  #
43
64
  # @return [NRSER::Types::Type]
44
65
  #
45
66
  attr_reader :type
46
67
 
47
-
68
+
69
+ # Names of any props this one depends on (to create a default).
70
+ #
71
+ # @return [Array<Symbol>]
72
+ #
73
+ attr_reader :deps
74
+
75
+
48
76
  # Optional name of instance variable (including the `@` prefix) or getter
49
77
  # method (method that takes no arguments) that provides the property's
50
78
  # value.
@@ -68,6 +96,13 @@ class NRSER::Meta::Props::Prop
68
96
  attr_reader :source
69
97
 
70
98
 
99
+ # TODO document `aliases` attribute.
100
+ #
101
+ # @return [Array<Symbol>]
102
+ #
103
+ attr_reader :aliases
104
+
105
+
71
106
  # Constructor
72
107
  # =====================================================================
73
108
 
@@ -75,8 +110,8 @@ class NRSER::Meta::Props::Prop
75
110
  #
76
111
  # You should not need to construct a `Prop` directly unless you are doing
77
112
  # custom meta-programming - they should be constructed for you via the
78
- # `.prop` "macro" defined at {NRSER::Meta::Props::ClassMethods#prop}
79
- # that is extended in to classes including {NRSER::Meta::Props}.
113
+ # `.prop` "macro" defined at {NRSER::Props::Props::ClassMethods#prop}
114
+ # that is extended in to classes including {NRSER::Props::Props}.
80
115
  #
81
116
  # @param [nil | Proc | Object] default:
82
117
  # A default value or a {Proc} used to get default values for *primary*
@@ -101,16 +136,29 @@ class NRSER::Meta::Props::Prop
101
136
  default: nil,
102
137
  source: nil,
103
138
  to_data: nil,
104
- from_data: nil
139
+ from_data: nil,
140
+ index: nil,
141
+ reader: nil,
142
+ writer: nil,
143
+ aliases: []
105
144
 
106
145
  # Set these up first so {#to_s} works in case we need to raise errors.
107
146
  @defined_in = defined_in
108
147
  @name = t.sym.check name
148
+ @index = t.non_neg_int?.check! index
109
149
  @type = t.make type
110
150
 
151
+ # Will be overridden in {#init_default!} if needed
152
+ @deps = []
153
+
111
154
  @to_data = to_data
112
155
  @from_data = from_data
113
156
 
157
+ @reader = t.bool?.check! reader
158
+ @writer = t.bool?.check! writer
159
+
160
+ @aliases = t.array( t.sym ).check! aliases
161
+
114
162
  # Source
115
163
 
116
164
  # normalize source to {nil}, {Symbol} or {Proc}
@@ -147,7 +195,7 @@ class NRSER::Meta::Props::Prop
147
195
  # for sourced props
148
196
  if source?
149
197
  raise ArgumentError.new binding.erb <<-END
150
- Can not construct {<%= self.class.name %>} with `default` and `source`
198
+ Can not construct {<%= self.class.safe_name %>} with `default` and `source`
151
199
 
152
200
  Props with {#source} always get their value from that source, so
153
201
  defaults don't make any sense.
@@ -166,8 +214,47 @@ class NRSER::Meta::Props::Prop
166
214
  END
167
215
  end
168
216
 
169
- # It must be a {Proc} or be frozen
170
- unless Proc === default || default.frozen?
217
+ if Proc === default
218
+ case default.arity
219
+ when 0
220
+ # pass, no deps
221
+ when 1
222
+ # Check that it's valid and set deps
223
+ @deps = default.parameters.map do |param|
224
+ unless Array === param &&
225
+ :keyreq == param[0]
226
+ raise ArgumentError.new binding.erb <<~END
227
+ Prop default Proc that take args must take only required
228
+ keywords (`:keyreq` type)
229
+
230
+ This is because this is how the props system figures out
231
+ any dependency orders.
232
+
233
+ Found:
234
+
235
+ <%= default.parameters %>
236
+
237
+ For `default` for prop <%= full_name %>:
238
+
239
+ <%= self.pretty_inspect %>
240
+
241
+ END
242
+ end
243
+
244
+ # The keyword name
245
+ param[1]
246
+ end
247
+ else
248
+ raise ArgumentError.new binding.erb <<~END
249
+ Prop default Proc must take no params or only required keywords
250
+ ({Proc#arity} of 0 or 1).
251
+
252
+ Default to prop <%= full_name %> has arity <%= default.arity %>.
253
+
254
+ END
255
+ end
256
+
257
+ elsif !default.frozen?
171
258
  raise ArgumentError.new binding.erb <<-END
172
259
  Non-proc default values must be frozen
173
260
 
@@ -195,13 +282,21 @@ class NRSER::Meta::Props::Prop
195
282
  # Instance Methods
196
283
  # ============================================================================
197
284
 
198
- # Used by the {NRSER::Meta::Props::ClassMethods.prop} "macro" method to
285
+ def names
286
+ [name, *aliases]
287
+ end
288
+
289
+
290
+ # Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
199
291
  # determine if it should create a reader method on the propertied class.
200
292
  #
201
293
  # @return [Boolean]
202
294
  # `true` if a reader method should be created for the prop value.
203
295
  #
204
- def create_reader?
296
+ def create_reader? name
297
+ # If the options was explicitly provided then return that
298
+ return @reader unless @reader.nil?
299
+
205
300
  # Always create readers for primary props
206
301
  return true if primary?
207
302
 
@@ -216,7 +311,7 @@ class NRSER::Meta::Props::Prop
216
311
  end # #create_reader?
217
312
 
218
313
 
219
- # Used by the {NRSER::Meta::Props::ClassMethods.prop} "macro" method to
314
+ # Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
220
315
  # determine if it should create a writer method on the propertied class.
221
316
  #
222
317
  # Right now, we don't create writers, but we will probably make them an
@@ -225,7 +320,13 @@ class NRSER::Meta::Props::Prop
225
320
  # @return [Boolean]
226
321
  # Always `false` for the moment.
227
322
  #
228
- def create_writer?
323
+ def create_writer? name
324
+ return @writer unless @writer.nil?
325
+
326
+ storage_immutable = defined_in.metadata.storage.try( :immutable? )
327
+
328
+ return !storage_immutable unless storage_immutable.nil?
329
+
229
330
  false
230
331
  end # #create_writer?
231
332
 
@@ -259,16 +360,37 @@ class NRSER::Meta::Props::Prop
259
360
  alias_method :default?, :has_default?
260
361
 
261
362
 
262
- def default
363
+ # Get the default value for the property given the instance and values.
364
+ #
365
+ # @todo
366
+ # This is a shitty hack stop-gap until I really figure our how this should
367
+ # work.
368
+ #
369
+ # @param [Hash<Symbol, Object>] values
370
+ # Other prop values known at this point, keyed by name.
371
+ #
372
+ # @return [Object]
373
+ # Default value.
374
+ #
375
+ # @raise [NameError]
376
+ # If the prop doesn't have a default.
377
+ #
378
+ def default **values
263
379
  if has_default?
264
380
  if Proc === @default
265
- @default.call
381
+ case @default.arity
382
+ when 0
383
+ @default.call
384
+ else
385
+ kwds = values.slice *deps
386
+ @default.call **kwds
387
+ end
266
388
  else
267
389
  @default
268
390
  end
269
391
  else
270
- raise NameError.new NRSER.squish <<-END
271
- Prop #{ self } has no default value.
392
+ raise NameError.new binding.erb <<-END
393
+ Prop <%= full_name %> has no default value (and none provided).
272
394
  END
273
395
  end
274
396
  end
@@ -309,100 +431,107 @@ class NRSER::Meta::Props::Prop
309
431
  end # #primary?
310
432
 
311
433
 
312
- # @todo Document get method.
434
+ # Get the value of the prop from an instance.
313
435
  #
314
- # @param [type] arg_name
315
- # @todo Add name param description.
436
+ # @note
437
+ # At the moment, values are **not** type-checked when reading. Primary
438
+ # values are checked when setting, so they should be ok, but this does
439
+ # leave the possibility that props with a {#source} may return values
440
+ # that do not satisfy their types... :/
316
441
  #
317
- # @return [return_type]
318
- # @todo Document return value.
442
+ # @param [NRSER::Props] instance
443
+ # An instance of {#defined_in}.
444
+ #
445
+ # @return
446
+ # Value from the instance's prop value storage (for {#primary?} props)
447
+ # or it's {#source}.
319
448
  #
320
449
  def get instance
321
450
  if source?
322
451
  if instance_variable_source?
323
452
  instance.instance_variable_get source
324
453
  else
325
- case source
326
- when String, Symbol
327
- instance.send source
328
- when Proc
329
- instance.instance_exec &source
330
- else
331
- raise TypeError.squished <<-END
332
- Expected `Prop#source` to be a String, Symbol or Proc;
333
- found #{ source.inspect }
334
- END
335
- end
454
+ t.match source,
455
+ t.or( String, Symbol ),
456
+ ->( name ) { instance.send name },
457
+ Proc,
458
+ ->( block ) { instance.instance_exec &block }
336
459
  end
337
460
  else
338
- values(instance)[name]
461
+ # Go through the storage engine
462
+ instance.class.metadata.storage.get instance, self
339
463
  end
340
464
  end # #get
341
465
 
342
466
 
343
- # @todo Document set method.
467
+ # Set a value for a the prop on an instance.
344
468
  #
345
- # @param [type] arg_name
346
- # @todo Add name param description.
469
+ # @param [NRSER::Props] instance
470
+ # An instance of {#defined_in}.
347
471
  #
348
- # @return [return_type]
349
- # @todo Document return value.
472
+ # @param [*] value
473
+ # A value that must satisfy {#type}.
474
+ #
475
+ # @return [nil]
476
+ #
477
+ # @raise [RuntimeError]
478
+ # If you try to set a value for a prop that isn't {#primary?}.
479
+ #
480
+ # @raise (see #check!)
350
481
  #
351
482
  def set instance, value
352
- type.check( value ) do
353
- binding.erb <<-END
354
- Value of type <%= value.class.name %> for prop <%= self.full_name %>
355
- failed type check.
483
+ unless primary?
484
+ raise RuntimeError.new binding.erb <<~END
485
+ Only {#primary?} props can be set!
356
486
 
357
- Must satisfy type:
487
+ Tried to set prop #{ prop.name } to value
358
488
 
359
- <%= type %>
489
+ <%= value.pretty_inspect %>
360
490
 
361
- Given value:
491
+ in instance
362
492
 
363
- <%= value.pretty_inspect %>
493
+ <%= instance.pretty_inspect %>
364
494
 
365
495
  END
366
496
  end
367
497
 
368
- values(instance)[name] = value
498
+ instance.class.metadata.storage.put \
499
+ instance,
500
+ self,
501
+ check!( value )
502
+
503
+ nil
369
504
  end # #set
370
505
 
371
506
 
372
- # @todo Document set_from_hash method.
507
+ # Check that a value satisfies the {#type}, raising if it doesn't.
373
508
  #
374
- # @param [type] arg_name
375
- # @todo Add name param description.
509
+ # @param [VALUE] value
510
+ # Value to check.
376
511
  #
377
- # @return [return_type]
378
- # @todo Document return value.
512
+ # @return [VALUE]
513
+ # `value` arg that was passed in.
379
514
  #
380
- def set_from_values_hash instance, **values
381
- if values.key? name
382
- set instance, values[name]
383
- else
384
- if default?
385
- # set instance, if !default.nil? && default.respond_to?( :dup )
386
- # default.dup
387
- # else
388
- # default
389
- # end
390
- set instance, default
391
- else
392
- raise TypeError.new binding.erb <<-ERB
393
- Prop <%= full_name %> has no default value and no value was provided
394
- in values:
395
-
396
- <%= values.pretty_inspect %>
397
-
398
- Prop:
399
-
400
- <%= self.pretty_inspect %>
401
-
402
- ERB
403
- end
515
+ # @raise [NRSER::Types::CheckError]
516
+ # If `value` does not satisfy {#type}.
517
+ #
518
+ def check! value
519
+ type.check!( value ) do
520
+ binding.erb <<-END
521
+ Value of type <%= value.class.safe_name %> for prop <%= self.full_name %>
522
+ failed type check.
523
+
524
+ Must satisfy type:
525
+
526
+ <%= type %>
527
+
528
+ Given value:
529
+
530
+ <%= value.pretty_inspect %>
531
+
532
+ END
404
533
  end
405
- end # #set_from_hash
534
+ end # #check!
406
535
 
407
536
 
408
537
  # Get the "data" value - a basic scalar or structure of hashes, arrays and
@@ -438,7 +567,7 @@ class NRSER::Meta::Props::Prop
438
567
  # - The `to_data:` proc is called with the property value as the sole
439
568
  # argument and the result is returned as the data.
440
569
  #
441
- # @param [NRSER::Meta::Props] instance
570
+ # @param [NRSER::Props::Props] instance
442
571
  # Instance to get the property value form.
443
572
  #
444
573
  # @return [Object]
@@ -474,13 +603,12 @@ class NRSER::Meta::Props::Prop
474
603
  end # #to_data
475
604
 
476
605
 
477
- # @todo Document value_from_data method.
606
+ # Load a value for the prop from "data".
478
607
  #
479
- # @param [type] arg_name
480
- # @todo Add name param description.
608
+ # @param [*] data
481
609
  #
482
- # @return [return_type]
483
- # @todo Document return value.
610
+ # @return [VALUE]
611
+ # The prop value to use.
484
612
  #
485
613
  def value_from_data data
486
614
  value = case @from_data
@@ -498,7 +626,7 @@ class NRSER::Meta::Props::Prop
498
626
  # The custom `from_data` configuration specifies a string or symbol name,
499
627
  # which we interpret as a class method on the defining class and call
500
628
  # with the data to produce a value.
501
- @defined_in.send @to_data, data
629
+ @defined_in.send @from_data, data
502
630
 
503
631
  when Proc
504
632
  # The custom `from_data` configuration provides a procedure, which we
@@ -536,30 +664,7 @@ class NRSER::Meta::Props::Prop
536
664
  # a short string describing the instance.
537
665
  #
538
666
  def to_s
539
- "#<#{ self.class.name } #{ full_name }:#{ type }>"
667
+ "#<#{ self.class.safe_name } #{ full_name }:#{ type }>"
540
668
  end # #to_s
541
669
 
542
-
543
- private
544
-
545
- # @todo Document values method.
546
- #
547
- # @param [type] arg_name
548
- # @todo Add name param description.
549
- #
550
- # @return [return_type]
551
- # @todo Document return value.
552
- #
553
- def values instance
554
- unless instance.instance_variable_defined?(
555
- NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
556
- )
557
- instance.instance_variable_set \
558
- NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME, {}
559
- end
560
-
561
- instance.instance_variable_get \
562
- NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
563
- end # #value
564
-
565
- end # class NRSER::Meta::Props::Prop
670
+ end # class NRSER::Props::Prop