ryo.rb 0.5.3 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/specs.yml +2 -2
- data/README.md +30 -14
- data/Rakefile.rb +13 -0
- data/lib/ryo/basic_object.rb +7 -11
- data/lib/ryo/builder.rb +35 -54
- data/lib/ryo/enumerable.rb +62 -79
- data/lib/ryo/object.rb +6 -10
- data/lib/ryo/reflect.rb +55 -155
- data/lib/ryo/utils.rb +68 -0
- data/lib/ryo/version.rb +1 -1
- data/lib/ryo/yaml.rb +45 -0
- data/lib/ryo.rb +24 -37
- data/ryo.rb.gemspec +1 -0
- data/share/ryo.rb/examples/1.0_prototypes_point_object.rb +1 -0
- data/share/ryo.rb/examples/1.1_prototypes_ryo_fn.rb +1 -0
- data/share/ryo.rb/examples/2.0_iteration_each.rb +1 -0
- data/share/ryo.rb/examples/2.1_iteration_map.rb +1 -0
- data/share/ryo.rb/examples/2.2_iteration_ancestors.rb +1 -0
- data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +1 -0
- data/share/ryo.rb/examples/3.1_recursion_ryo_from_with_array.rb +1 -0
- data/share/ryo.rb/examples/3.2_recursion_ryo_from_with_openstruct.rb +1 -0
- data/share/ryo.rb/examples/4.0_basicobject_ryo_basicobject.rb +1 -0
- data/share/ryo.rb/examples/4.1_basicobject_ryo_basicobject_from.rb +1 -0
- data/share/ryo.rb/examples/5_collisions_resolution_strategy.rb +1 -0
- data/share/ryo.rb/examples/6_beyond_hash_objects.rb +1 -0
- data/share/ryo.rb/examples/7_ryo_memo.rb +1 -0
- data/spec/ryo_enumerable_spec.rb +1 -1
- data/spec/ryo_json_spec.rb +31 -13
- data/spec/ryo_reflect_spec.rb +8 -0
- data/spec/ryo_spec.rb +1 -1
- data/spec/ryo_yaml_spec.rb +44 -0
- metadata +8 -5
- data/.gitlab-ci.yml +0 -9
data/lib/ryo/reflect.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::Reflect Ryo::Reflect} module
|
5
|
-
#
|
6
|
-
# and
|
7
|
-
# [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
4
|
+
# The {Ryo::Reflect Ryo::Reflect} module mirrors
|
5
|
+
# JavaScript's [`Relfect` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect),
|
6
|
+
# and some of the static methods on JavaScript's
|
7
|
+
# [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
8
|
+
# as well.
|
8
9
|
#
|
9
|
-
#
|
10
|
-
# instance methods of this module
|
11
|
-
# on the {Ryo Ryo}
|
10
|
+
# {Ryo::Reflect Ryo::Reflect} also implements Ryo-specific
|
11
|
+
# reflection features. The instance methods of this module
|
12
|
+
# are available as singleton methods on the {Ryo Ryo}
|
13
|
+
# module.
|
12
14
|
module Ryo::Reflect
|
13
15
|
extend self
|
14
16
|
|
@@ -16,7 +18,7 @@ module Ryo::Reflect
|
|
16
18
|
# @group JavaScript equivalents (Reflect)
|
17
19
|
|
18
20
|
##
|
19
|
-
# Equivalent to JavaScript's `Reflect.getPrototypeOf
|
21
|
+
# Equivalent to JavaScript's `Reflect.getPrototypeOf`
|
20
22
|
#
|
21
23
|
# @param [Ryo] ryo
|
22
24
|
# A Ryo object.
|
@@ -29,7 +31,7 @@ module Ryo::Reflect
|
|
29
31
|
end
|
30
32
|
|
31
33
|
##
|
32
|
-
# Equivalent to JavaScript's `Reflect.setPrototypeOf
|
34
|
+
# Equivalent to JavaScript's `Reflect.setPrototypeOf`
|
33
35
|
#
|
34
36
|
# @param [Ryo] ryo
|
35
37
|
# A Ryo object.
|
@@ -45,17 +47,14 @@ module Ryo::Reflect
|
|
45
47
|
end
|
46
48
|
|
47
49
|
##
|
48
|
-
# Equivalent to JavaScript's `Reflect.defineProperty
|
50
|
+
# Equivalent to JavaScript's `Reflect.defineProperty`
|
49
51
|
#
|
50
52
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
51
|
-
# A Ryo object
|
52
|
-
#
|
53
|
+
# A Ryo object
|
53
54
|
# @param [<String, #to_s>] property
|
54
|
-
# The name of
|
55
|
-
#
|
55
|
+
# The name of a property
|
56
56
|
# @param [Object, BasicObject] value
|
57
|
-
# The value
|
58
|
-
#
|
57
|
+
# The property's value
|
59
58
|
# @return [void]
|
60
59
|
def define_property(ryo, property, value)
|
61
60
|
table, property = table_of(ryo), property.to_s
|
@@ -76,13 +75,12 @@ module Ryo::Reflect
|
|
76
75
|
|
77
76
|
##
|
78
77
|
# Equivalent to JavaScript's `Reflect.ownKeys`, and
|
79
|
-
# JavaScript's `Object.keys
|
78
|
+
# JavaScript's `Object.keys`
|
80
79
|
#
|
81
80
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
82
|
-
# A Ryo object
|
83
|
-
#
|
81
|
+
# A Ryo object
|
84
82
|
# @return [Array<String>]
|
85
|
-
# Returns the properties defined on a Ryo object
|
83
|
+
# Returns the properties defined on a Ryo object
|
86
84
|
def properties_of(ryo)
|
87
85
|
table_of(ryo).keys
|
88
86
|
end
|
@@ -97,13 +95,11 @@ module Ryo::Reflect
|
|
97
95
|
# and `Object.prototype.hasOwnProperty`.
|
98
96
|
#
|
99
97
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
100
|
-
# A Ryo object
|
101
|
-
#
|
98
|
+
# A Ryo object
|
102
99
|
# @param [<String, #to_s>] property
|
103
|
-
#
|
104
|
-
#
|
100
|
+
# The name of a property
|
105
101
|
# @return [Boolean]
|
106
|
-
# Returns true when
|
102
|
+
# Returns true when the property is a member of a Ryo object
|
107
103
|
def property?(ryo, property)
|
108
104
|
table_of(ryo).key?(property.to_s)
|
109
105
|
end
|
@@ -111,14 +107,11 @@ module Ryo::Reflect
|
|
111
107
|
##
|
112
108
|
# Equivalent to JavaScript's `Object.assign`.
|
113
109
|
#
|
114
|
-
#
|
115
110
|
# @param [Ryo, Hash, #to_hash] target
|
116
|
-
# The target object
|
117
|
-
#
|
111
|
+
# The target object
|
118
112
|
# @param [Ryo, Hash, #to_hash] sources
|
119
113
|
# A variable number of source objects that
|
120
|
-
# will be merged
|
121
|
-
#
|
114
|
+
# will be merged with the target object
|
122
115
|
# @return [Ryo]
|
123
116
|
# Returns the modified target object.
|
124
117
|
def assign(target, *sources)
|
@@ -134,16 +127,13 @@ module Ryo::Reflect
|
|
134
127
|
|
135
128
|
##
|
136
129
|
# The {#delete!} method deletes a property from a Ryo object,
|
137
|
-
# and from the prototypes in its prototype chain
|
130
|
+
# and from the prototypes in its prototype chain
|
138
131
|
#
|
139
132
|
# @see Ryo::Keywords#delete
|
140
|
-
#
|
141
133
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
142
|
-
# A Ryo object
|
143
|
-
#
|
134
|
+
# A Ryo object
|
144
135
|
# @param [<String, #to_s>] property
|
145
|
-
#
|
146
|
-
#
|
136
|
+
# The name of a property
|
147
137
|
# @return [void]
|
148
138
|
def delete!(ryo, property)
|
149
139
|
[ryo, *prototype_chain_of(ryo)].each do
|
@@ -153,10 +143,9 @@ module Ryo::Reflect
|
|
153
143
|
|
154
144
|
##
|
155
145
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
156
|
-
# A Ryo object
|
157
|
-
#
|
146
|
+
# A Ryo object
|
158
147
|
# @return [Array<Ryo::Object, Ryo::BasicObject>]
|
159
|
-
# Returns the prototype chain of a Ryo object
|
148
|
+
# Returns the prototype chain of a Ryo object
|
160
149
|
def prototype_chain_of(ryo)
|
161
150
|
prototypes = []
|
162
151
|
loop do
|
@@ -169,20 +158,21 @@ module Ryo::Reflect
|
|
169
158
|
|
170
159
|
##
|
171
160
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
172
|
-
# A Ryo object
|
173
|
-
#
|
161
|
+
# A Ryo object
|
174
162
|
# @param [Boolean] recursive
|
175
163
|
# When true, nested Ryo objects are replaced by
|
176
|
-
# their table as well
|
177
|
-
#
|
164
|
+
# their table as well
|
178
165
|
# @return [Hash]
|
179
|
-
# Returns the table of a Ryo object
|
166
|
+
# Returns the table of a Ryo object
|
180
167
|
def table_of(ryo, recursive: false)
|
181
168
|
table = kernel(:instance_variable_get).bind_call(ryo, :@_table)
|
182
169
|
if recursive
|
183
170
|
table.each do |key, value|
|
184
171
|
if ryo?(value)
|
185
172
|
table[key] = table_of(value, recursive:)
|
173
|
+
elsif value.respond_to?(:each)
|
174
|
+
table[key] = value.respond_to?(:each_pair) ?
|
175
|
+
value : value.map { table_of(_1, recursive:) }
|
186
176
|
end
|
187
177
|
end
|
188
178
|
end
|
@@ -190,14 +180,12 @@ module Ryo::Reflect
|
|
190
180
|
end
|
191
181
|
|
192
182
|
##
|
193
|
-
# Sets the table of a Ryo object
|
183
|
+
# Sets the table of a Ryo object
|
194
184
|
#
|
195
185
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
196
|
-
# A Ryo object
|
197
|
-
#
|
186
|
+
# A Ryo object
|
198
187
|
# @param [Hash] table
|
199
|
-
# The table
|
200
|
-
#
|
188
|
+
# The table
|
201
189
|
# @return [nil]
|
202
190
|
def set_table_of(ryo, table)
|
203
191
|
kernel(:instance_variable_set)
|
@@ -207,19 +195,14 @@ module Ryo::Reflect
|
|
207
195
|
|
208
196
|
##
|
209
197
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
210
|
-
# A Ryo object
|
211
|
-
#
|
198
|
+
# A Ryo object
|
212
199
|
# @param [<String, Symbol>] method
|
213
|
-
# The name of a method
|
214
|
-
#
|
200
|
+
# The name of a method
|
215
201
|
# @param [::Object, ::BasicObject] args
|
216
|
-
# Zero or more
|
217
|
-
#
|
202
|
+
# Zero or more method arguments
|
218
203
|
# @param [Proc] b
|
219
|
-
# An optional block
|
220
|
-
#
|
204
|
+
# An optional block
|
221
205
|
# @return [::Object, ::BasicObject]
|
222
|
-
# Returns the return value of the method call.
|
223
206
|
def call_method(ryo, method, *args, &b)
|
224
207
|
kernel(:__send__)
|
225
208
|
.bind_call(ryo, method, *args, &b)
|
@@ -227,31 +210,27 @@ module Ryo::Reflect
|
|
227
210
|
|
228
211
|
##
|
229
212
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
230
|
-
# A Ryo object
|
231
|
-
#
|
213
|
+
# A Ryo object
|
232
214
|
# @return [Class]
|
233
|
-
# Returns the class of a Ryo object
|
215
|
+
# Returns the class of a Ryo object
|
234
216
|
def class_of(ryo)
|
235
217
|
kernel(:class).bind_call(ryo)
|
236
218
|
end
|
237
219
|
|
238
220
|
##
|
239
221
|
# @param [Ryo::Function, Object, BasicObject] obj
|
240
|
-
# An object
|
241
|
-
#
|
222
|
+
# An object
|
242
223
|
# @return [Boolean]
|
243
|
-
# Returns true when
|
224
|
+
# Returns true when given a Ryo function
|
244
225
|
def function?(obj)
|
245
226
|
Ryo::Function === obj
|
246
227
|
end
|
247
228
|
|
248
229
|
##
|
249
230
|
# @param [Ryo::Function, Object, BasicObject] obj
|
250
|
-
# An object
|
251
|
-
#
|
231
|
+
# An object
|
252
232
|
# @return [Boolean]
|
253
|
-
# Returns true when
|
254
|
-
# of {Ryo::Memo Ryo::Memo}.
|
233
|
+
# Returns true when given a Ryo memo
|
255
234
|
def memo?(obj)
|
256
235
|
Ryo::Memo === obj
|
257
236
|
end
|
@@ -264,33 +243,29 @@ module Ryo::Reflect
|
|
264
243
|
# Ryo.ryo?(Object.new) # => false
|
265
244
|
#
|
266
245
|
# @param [Object, BasicObject] obj
|
267
|
-
# An object
|
268
|
-
#
|
246
|
+
# An object
|
269
247
|
# @return [Boolean]
|
270
|
-
# Returns true when
|
248
|
+
# Returns true when given a Ryo object
|
271
249
|
def ryo?(obj)
|
272
250
|
Ryo === obj
|
273
251
|
end
|
274
252
|
|
275
253
|
##
|
276
254
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo1
|
277
|
-
# A Ryo object
|
278
|
-
#
|
255
|
+
# A Ryo object
|
279
256
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo2
|
280
|
-
# A Ryo object
|
281
|
-
#
|
257
|
+
# A Ryo object
|
282
258
|
# @return [Boolean]
|
283
|
-
# Returns true when two Ryo objects are
|
259
|
+
# Returns true when the two Ryo objects are strictly equal
|
284
260
|
def equal?(ryo1, ryo2)
|
285
261
|
kernel(:equal?).bind_call(ryo1, ryo2)
|
286
262
|
end
|
287
263
|
|
288
264
|
##
|
289
265
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
290
|
-
# A Ryo object
|
291
|
-
#
|
266
|
+
# A Ryo object
|
292
267
|
# @return [String]
|
293
|
-
# Returns a String representation of a Ryo object
|
268
|
+
# Returns a String representation of a Ryo object
|
294
269
|
def inspect_object(ryo)
|
295
270
|
format(
|
296
271
|
"#<Ryo object=%{object} proto=%{proto} table=%{table}>",
|
@@ -301,80 +276,5 @@ module Ryo::Reflect
|
|
301
276
|
end
|
302
277
|
# @endgroup
|
303
278
|
|
304
|
-
|
305
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
306
|
-
# A Ryo object.
|
307
|
-
#
|
308
|
-
# @param [<String, Symbol>] method
|
309
|
-
# The name of the method.
|
310
|
-
#
|
311
|
-
# @param [Proc] b
|
312
|
-
# The method's body.
|
313
|
-
#
|
314
|
-
# @private
|
315
|
-
private def define_method!(ryo, method, &b)
|
316
|
-
kernel(:define_singleton_method)
|
317
|
-
.bind_call(ryo, method, &b)
|
318
|
-
end
|
319
|
-
|
320
|
-
##
|
321
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
322
|
-
# A Ryo object.
|
323
|
-
#
|
324
|
-
# @param [<String, #to_s>] property
|
325
|
-
# The name of the property.
|
326
|
-
#
|
327
|
-
# @return [Boolean]
|
328
|
-
# Returns true when the property has been
|
329
|
-
# defined with a getter method.
|
330
|
-
#
|
331
|
-
# @private
|
332
|
-
private def getter_defined?(ryo, property)
|
333
|
-
kernel(:method)
|
334
|
-
.bind_call(ryo, property)
|
335
|
-
.source_location
|
336
|
-
&.dig(0) == __FILE__
|
337
|
-
end
|
338
|
-
|
339
|
-
##
|
340
|
-
#
|
341
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
342
|
-
# A Ryo object.
|
343
|
-
#
|
344
|
-
# @param [<String, #to_s>] property
|
345
|
-
# The name of the property.
|
346
|
-
#
|
347
|
-
# @return [Boolean]
|
348
|
-
# Returns true when the property has been
|
349
|
-
# defined with a setter method.
|
350
|
-
#
|
351
|
-
# @private
|
352
|
-
private def setter_defined?(ryo, property)
|
353
|
-
getter_defined?(ryo, "#{property}=")
|
354
|
-
end
|
355
|
-
|
356
|
-
##
|
357
|
-
# @private
|
358
|
-
private def merge!(obj1, obj2)
|
359
|
-
obj1, obj2 = to_hash(obj1), to_hash(obj2)
|
360
|
-
obj2.each { obj1[_1.to_s] = _2 }
|
361
|
-
obj1
|
362
|
-
end
|
363
|
-
|
364
|
-
##
|
365
|
-
# @private
|
366
|
-
private def to_hash(obj)
|
367
|
-
if ryo?(obj)
|
368
|
-
table_of(obj)
|
369
|
-
else
|
370
|
-
Hash.try_convert(obj)
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
##
|
375
|
-
# @private
|
376
|
-
def kernel(name)
|
377
|
-
Module.instance_method(name)
|
378
|
-
end
|
379
|
-
# @endgroup
|
279
|
+
include Ryo::Utils
|
380
280
|
end
|
data/lib/ryo/utils.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::Utils Ryo::Utils} module provides utility
|
5
|
+
# methods that are internal to Ryo. This module
|
6
|
+
# and its methods should not be used directly.
|
7
|
+
# @api private
|
8
|
+
module Ryo::Utils
|
9
|
+
private
|
10
|
+
|
11
|
+
##
|
12
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
13
|
+
# A Ryo object
|
14
|
+
# @param [<String, Symbol>] method
|
15
|
+
# The name of a method
|
16
|
+
# @param [Proc] b
|
17
|
+
# The method's implementation
|
18
|
+
def define_method!(ryo, method, &b)
|
19
|
+
kernel(:define_singleton_method)
|
20
|
+
.bind_call(ryo, method, &b)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
25
|
+
# A Ryo object
|
26
|
+
# @param [<String, #to_s>] property
|
27
|
+
# The name of a property
|
28
|
+
# @return [Boolean]
|
29
|
+
# Returns true for a Ryo property that has a
|
30
|
+
# corresponding getter method implemented by Ryo
|
31
|
+
def getter_defined?(ryo, property)
|
32
|
+
path = kernel(:method)
|
33
|
+
.bind_call(ryo, property)
|
34
|
+
.source_location
|
35
|
+
&.dig(0)
|
36
|
+
path ? File.dirname(path) == File.dirname(__FILE__) : false
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
41
|
+
# A Ryo object
|
42
|
+
# @param [<String, #to_s>] property
|
43
|
+
# The name of a property
|
44
|
+
# @return [Boolean]
|
45
|
+
# Returns true for a Ryo property that has a
|
46
|
+
# corresponding setter method implemented by Ryo
|
47
|
+
def setter_defined?(ryo, property)
|
48
|
+
getter_defined?(ryo, "#{property}=")
|
49
|
+
end
|
50
|
+
|
51
|
+
def merge!(obj1, obj2)
|
52
|
+
obj1, obj2 = to_hash(obj1), to_hash(obj2)
|
53
|
+
obj2.each { obj1[_1.to_s] = _2 }
|
54
|
+
obj1
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_hash(obj)
|
58
|
+
if ryo?(obj)
|
59
|
+
table_of(obj)
|
60
|
+
else
|
61
|
+
Hash.try_convert(obj)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def kernel(name)
|
66
|
+
Module.instance_method(name)
|
67
|
+
end
|
68
|
+
end
|
data/lib/ryo/version.rb
CHANGED
data/lib/ryo/yaml.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::YAML Ryo::YAML} module provides a number of methods
|
5
|
+
# for coercing YAML data into a Ryo object. It must be required
|
6
|
+
# separately to Ryo (ie: require "ryo/yaml"), and the methods of
|
7
|
+
# this module are then available on the {Ryo Ryo} module.
|
8
|
+
module Ryo::YAML
|
9
|
+
require "yaml"
|
10
|
+
extend self
|
11
|
+
|
12
|
+
##
|
13
|
+
# @example
|
14
|
+
# Ryo.from_yaml(path: "/foo/bar/baz.yaml")
|
15
|
+
# Ryo.from_yaml(string: "---\nfoo: bar\n")
|
16
|
+
#
|
17
|
+
# @param [String] path
|
18
|
+
# The path to a YAML file
|
19
|
+
#
|
20
|
+
# @param [String] string
|
21
|
+
# A blob of YAML
|
22
|
+
#
|
23
|
+
# @param [Ryo] object
|
24
|
+
# {Ryo::Object Ryo::Object}, or {Ryo::BasicObject Ryo::BasicObject}
|
25
|
+
# Defaults to {Ryo::Object Ryo::Object}
|
26
|
+
#
|
27
|
+
# @raise [SystemCallError]
|
28
|
+
# Might raise a number of Errno exceptions
|
29
|
+
#
|
30
|
+
# @return [Ryo::Object, Ryo::BasicObject]
|
31
|
+
# Returns a Ryo object
|
32
|
+
def from_yaml(path: nil, string: nil, object: Ryo::Object)
|
33
|
+
if path && string
|
34
|
+
raise ArgumentError, "Provide a path or string but not both"
|
35
|
+
elsif path
|
36
|
+
object.from YAML.load_file(path)
|
37
|
+
elsif string
|
38
|
+
object.from YAML.load(string)
|
39
|
+
else
|
40
|
+
raise ArgumentError, "No path or string provided"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Ryo.extend(self)
|
45
|
+
end
|
data/lib/ryo.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
# point = Ryo.assign(Ryo({}), {x: 0}, {y: 0})
|
16
16
|
# point.x # => 0
|
17
17
|
module Ryo
|
18
|
+
require_relative "ryo/utils"
|
18
19
|
require_relative "ryo/reflect"
|
19
20
|
require_relative "ryo/keywords"
|
20
21
|
require_relative "ryo/builder"
|
@@ -30,13 +31,11 @@ module Ryo
|
|
30
31
|
|
31
32
|
##
|
32
33
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
33
|
-
# A Ryo object
|
34
|
-
#
|
34
|
+
# A Ryo object
|
35
35
|
# @param [Module] mod
|
36
|
-
#
|
37
|
-
#
|
36
|
+
# The module to extend a Ryo object with
|
38
37
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
39
|
-
# Returns
|
38
|
+
# Returns an extended Ryo object
|
40
39
|
def self.extend!(ryo, mod)
|
41
40
|
kernel(:extend).bind_call(ryo, mod)
|
42
41
|
end
|
@@ -45,10 +44,9 @@ module Ryo
|
|
45
44
|
# Duplicates a Ryo object, and its prototype(s).
|
46
45
|
#
|
47
46
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
48
|
-
# A Ryo object
|
49
|
-
#
|
47
|
+
# A Ryo object
|
50
48
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
51
|
-
# Returns a duplicated Ryo object
|
49
|
+
# Returns a duplicated Ryo object
|
52
50
|
def self.dup(ryo)
|
53
51
|
duplicate = extend!(
|
54
52
|
kernel(:dup).bind_call(ryo),
|
@@ -61,13 +59,12 @@ module Ryo
|
|
61
59
|
end
|
62
60
|
|
63
61
|
##
|
64
|
-
# Creates a memoized Ryo value
|
62
|
+
# Creates a memoized Ryo value
|
65
63
|
#
|
66
64
|
# @param [Proc] b
|
67
|
-
# A Proc that is memoized after being accessed for the first time
|
68
|
-
#
|
65
|
+
# A Proc that is memoized after being accessed for the first time
|
69
66
|
# @return [Ryo::Memo]
|
70
|
-
# Returns an instance of {Ryo::Memo Ryo::Memo}
|
67
|
+
# Returns an instance of {Ryo::Memo Ryo::Memo}
|
71
68
|
def self.memo(&b)
|
72
69
|
Ryo::Memo.new(&b)
|
73
70
|
end
|
@@ -76,36 +73,32 @@ module Ryo
|
|
76
73
|
end
|
77
74
|
|
78
75
|
##
|
79
|
-
# Creates a Ryo object by recursively walking a Hash object
|
76
|
+
# Creates a Ryo object by recursively walking a Hash object
|
80
77
|
#
|
81
78
|
# @param props (see Ryo::Builder.build)
|
82
79
|
# @param prototype (see Ryo::Builder.build)
|
83
|
-
#
|
84
80
|
# @return [Ryo::Object]
|
85
|
-
# Returns an instance of {Ryo::Object Ryo::Object}
|
81
|
+
# Returns an instance of {Ryo::Object Ryo::Object}
|
86
82
|
def self.from(props, prototype = nil)
|
87
83
|
Ryo::Object.from(props, prototype)
|
88
84
|
end
|
89
85
|
|
90
86
|
##
|
91
|
-
# Returns the prototype of self, or "nil" if self has no prototype.
|
92
|
-
#
|
93
87
|
# @return [<Ryo::Object, Ryo::BasicObject>, nil]
|
88
|
+
# Returns the prototype of self, or nil if self has no prototype
|
94
89
|
def __proto__
|
95
90
|
@_proto
|
96
91
|
end
|
97
92
|
|
98
93
|
##
|
94
|
+
# @note
|
95
|
+
# This method will first query self for a property,
|
96
|
+
# and if the property is not found the query is sent
|
97
|
+
# to {Ryo#__proto__ Ryo#__proto__} instead
|
99
98
|
# @param [String] property
|
100
|
-
#
|
101
|
-
#
|
99
|
+
# The name of a property
|
102
100
|
# @return [<Object, BasicObject>, nil]
|
103
|
-
# Returns the value
|
104
|
-
#
|
105
|
-
# @note
|
106
|
-
# This method will first try to read **property** from self, and if
|
107
|
-
# it is not found on self the chain of prototypes will be traversed
|
108
|
-
# through instead.
|
101
|
+
# Returns the property's value, or nil
|
109
102
|
def [](property)
|
110
103
|
property = property.to_s
|
111
104
|
if Ryo.property?(self, property)
|
@@ -118,14 +111,11 @@ module Ryo
|
|
118
111
|
end
|
119
112
|
|
120
113
|
##
|
121
|
-
#
|
114
|
+
# Assign a property
|
122
115
|
#
|
123
116
|
# @param [String] property
|
124
|
-
#
|
125
|
-
#
|
117
|
+
# The name of a property
|
126
118
|
# @param [<Object,BasicObject>] value
|
127
|
-
# The value.
|
128
|
-
#
|
129
119
|
# @return [void]
|
130
120
|
def []=(property, value)
|
131
121
|
Ryo.define_property(self, property.to_s, value)
|
@@ -133,10 +123,8 @@ module Ryo
|
|
133
123
|
|
134
124
|
##
|
135
125
|
# @param [<Ryo::Object, Ryo::BasicObject>, Hash, #to_h] other
|
136
|
-
# An object to compare against.
|
137
|
-
#
|
138
126
|
# @return [Boolean]
|
139
|
-
# Returns true **other** is equal to self
|
127
|
+
# Returns true **other** is equal to self
|
140
128
|
def ==(other)
|
141
129
|
if Ryo.ryo?(other)
|
142
130
|
@_table == Ryo.table_of(other)
|
@@ -150,14 +138,14 @@ module Ryo
|
|
150
138
|
|
151
139
|
##
|
152
140
|
# @return [String]
|
153
|
-
# Returns a String representation of a Ryo object
|
141
|
+
# Returns a String representation of a Ryo object
|
154
142
|
def inspect
|
155
143
|
Ryo.inspect_object(self)
|
156
144
|
end
|
157
145
|
|
158
146
|
##
|
159
147
|
# @return [Hash]
|
160
|
-
# Returns the
|
148
|
+
# Returns the lookup table of a Ryo object
|
161
149
|
def to_h
|
162
150
|
Ryo.table_of(self, recursive: true)
|
163
151
|
end
|
@@ -200,9 +188,8 @@ end
|
|
200
188
|
##
|
201
189
|
# @param props (see Ryo::Builder.build)
|
202
190
|
# @param prototype (see Ryo::Builder.build)
|
203
|
-
#
|
204
191
|
# @return [Ryo::Object]
|
205
|
-
# Returns a Ryo object
|
192
|
+
# Returns a Ryo object
|
206
193
|
def Ryo(props, prototype = nil)
|
207
194
|
Ryo::Object.create(props, prototype)
|
208
195
|
end
|
data/ryo.rb.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.require_paths = ["lib"]
|
13
13
|
gem.description = "Ryo implements prototype-based inheritance, in Ruby"
|
14
14
|
gem.summary = gem.description
|
15
|
+
gem.required_ruby_version = ">= 3.2"
|
15
16
|
gem.add_development_dependency "yard", "~> 0.9"
|
16
17
|
gem.add_development_dependency "redcarpet", "~> 3.5"
|
17
18
|
gem.add_development_dependency "rspec", "~> 3.10"
|