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
@@ -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