ryo.rb 0.5.3 → 0.5.6
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.
- 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"
|