rupkl 0.2.0 → 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.
- checksums.yaml +4 -4
- data/lib/rupkl/node/amend_expression.rb +2 -2
- data/lib/rupkl/node/any.rb +15 -4
- data/lib/rupkl/node/base.rb +32 -2
- data/lib/rupkl/node/boolean.rb +26 -9
- data/lib/rupkl/node/collection.rb +176 -0
- data/lib/rupkl/node/data_size.rb +254 -0
- data/lib/rupkl/node/duration.rb +266 -0
- data/lib/rupkl/node/dynamic.rb +19 -15
- data/lib/rupkl/node/identifier.rb +5 -1
- data/lib/rupkl/node/if_expression.rb +45 -0
- data/lib/rupkl/node/intseq.rb +84 -0
- data/lib/rupkl/node/listing.rb +11 -4
- data/lib/rupkl/node/map.rb +120 -0
- data/lib/rupkl/node/mapping.rb +13 -6
- data/lib/rupkl/node/member_finder.rb +4 -10
- data/lib/rupkl/node/member_reference.rb +5 -3
- data/lib/rupkl/node/method_call.rb +2 -3
- data/lib/rupkl/node/method_definition.rb +74 -18
- data/lib/rupkl/node/node_common.rb +1 -1
- data/lib/rupkl/node/null.rb +1 -4
- data/lib/rupkl/node/number.rb +133 -45
- data/lib/rupkl/node/object.rb +322 -66
- data/lib/rupkl/node/operation.rb +123 -100
- data/lib/rupkl/node/pair.rb +58 -0
- data/lib/rupkl/node/pkl_module.rb +4 -4
- data/lib/rupkl/node/regex.rb +196 -0
- data/lib/rupkl/node/string.rb +155 -133
- data/lib/rupkl/node/struct_common.rb +70 -35
- data/lib/rupkl/node/value_common.rb +1 -5
- data/lib/rupkl/parser/expression.rb +43 -6
- data/lib/rupkl/parser/misc.rb +20 -0
- data/lib/rupkl/parser/object.rb +96 -13
- data/lib/rupkl/parser/pkl_class.rb +12 -5
- data/lib/rupkl/pkl_object.rb +2 -18
- data/lib/rupkl/version.rb +1 -1
- data/lib/rupkl.rb +10 -2
- metadata +17 -9
data/lib/rupkl/node/object.rb
CHANGED
@@ -21,30 +21,30 @@ module RuPkl
|
|
21
21
|
|
22
22
|
attr_writer :visibility
|
23
23
|
|
24
|
+
def generated?
|
25
|
+
@generated
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_writer :generated
|
29
|
+
|
24
30
|
private
|
25
31
|
|
26
32
|
def evaluate_value(evaluator, context)
|
27
33
|
@value_evaluated = value.__send__(evaluator, context)
|
28
34
|
value
|
29
35
|
end
|
30
|
-
|
31
|
-
def copy_value
|
32
|
-
if @value_evaluated.respond_to?(:body)
|
33
|
-
@value_evaluated.copy
|
34
|
-
else
|
35
|
-
@value.copy
|
36
|
-
end
|
37
|
-
end
|
38
36
|
end
|
39
37
|
|
40
38
|
class ObjectProperty < ObjectMember
|
41
|
-
def initialize(parent, name, value, position)
|
42
|
-
super
|
39
|
+
def initialize(parent, name, value, modifiers, position)
|
40
|
+
super(parent, name, value, position)
|
43
41
|
@name = name
|
44
42
|
@value = value
|
43
|
+
@modifiers = modifiers
|
45
44
|
end
|
46
45
|
|
47
46
|
attr_reader :name
|
47
|
+
attr_reader :modifiers
|
48
48
|
|
49
49
|
def evaluate(context = nil)
|
50
50
|
evaluate_value(__method__, context)
|
@@ -71,11 +71,19 @@ module RuPkl
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def ==(other)
|
74
|
-
name
|
74
|
+
name == other.name && value == other.value
|
75
75
|
end
|
76
76
|
|
77
|
-
def copy(parent = nil)
|
78
|
-
self.class.new(parent, name.copy,
|
77
|
+
def copy(parent = nil, position = @position)
|
78
|
+
self.class.new(parent, name.copy, value.copy, modifiers, position)
|
79
|
+
end
|
80
|
+
|
81
|
+
def local?
|
82
|
+
@modifiers&.[](:local) || false
|
83
|
+
end
|
84
|
+
|
85
|
+
def coexistable?(other)
|
86
|
+
name != other.name || local? != other.local? && !parent.equal?(other.parent)
|
79
87
|
end
|
80
88
|
|
81
89
|
private
|
@@ -128,8 +136,12 @@ module RuPkl
|
|
128
136
|
key == other.key && value == other.value
|
129
137
|
end
|
130
138
|
|
131
|
-
def copy(parent = nil)
|
132
|
-
self.class.new(parent, key,
|
139
|
+
def copy(parent = nil, position = @position)
|
140
|
+
self.class.new(parent, key, value.copy, position)
|
141
|
+
end
|
142
|
+
|
143
|
+
def coexistable?(other)
|
144
|
+
key != other.key
|
133
145
|
end
|
134
146
|
|
135
147
|
private
|
@@ -175,8 +187,8 @@ module RuPkl
|
|
175
187
|
value == other.value
|
176
188
|
end
|
177
189
|
|
178
|
-
def copy(parent = nil)
|
179
|
-
self.class.new(parent,
|
190
|
+
def copy(parent = nil, position = @position)
|
191
|
+
self.class.new(parent, value.copy, position)
|
180
192
|
end
|
181
193
|
|
182
194
|
private
|
@@ -186,39 +198,261 @@ module RuPkl
|
|
186
198
|
end
|
187
199
|
end
|
188
200
|
|
201
|
+
class WhenGenerator
|
202
|
+
include NodeCommon
|
203
|
+
|
204
|
+
def initialize(parent, condition, when_body, else_body, result, position)
|
205
|
+
super
|
206
|
+
@condition = condition
|
207
|
+
@when_body = when_body
|
208
|
+
@else_body = else_body
|
209
|
+
@result = result if result
|
210
|
+
end
|
211
|
+
|
212
|
+
attr_reader :condition
|
213
|
+
attr_reader :when_body
|
214
|
+
attr_reader :else_body
|
215
|
+
|
216
|
+
def resolve_generator(context = nil)
|
217
|
+
unless instance_variable_defined?(:@result)
|
218
|
+
@result =
|
219
|
+
if evaluate_condition(context)
|
220
|
+
when_body.resolve_generator(context)
|
221
|
+
else
|
222
|
+
else_body&.resolve_generator(context)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
def copy(parent = nil, position = @position)
|
230
|
+
if result
|
231
|
+
self.class.new(parent, nil, nil, nil, result.copy, position)
|
232
|
+
else
|
233
|
+
copies = [condition, when_body, else_body].map { _1&.copy }
|
234
|
+
self.class.new(parent, *copies, nil, position)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def collect_members(klass)
|
239
|
+
result&.collect_members(klass)
|
240
|
+
end
|
241
|
+
|
242
|
+
private
|
243
|
+
|
244
|
+
attr_reader :result
|
245
|
+
|
246
|
+
def evaluate_condition(context)
|
247
|
+
result =
|
248
|
+
(context || current_context.pop).then do |c|
|
249
|
+
condition.evaluate(c)
|
250
|
+
end
|
251
|
+
return result.value if result.is_a?(Boolean)
|
252
|
+
|
253
|
+
message =
|
254
|
+
'expected type \'Boolean\', ' \
|
255
|
+
"but got type '#{result.class_name}'"
|
256
|
+
raise EvaluationError.new(message, position)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class ForGenerator
|
261
|
+
include NodeCommon
|
262
|
+
|
263
|
+
def initialize(parent, key_name, value_name, iterable, body, results, position)
|
264
|
+
super(parent, key_name, value_name, iterable, body, *results, position)
|
265
|
+
@key_name = key_name
|
266
|
+
@value_name = value_name
|
267
|
+
@iterable = iterable
|
268
|
+
@body = body
|
269
|
+
@results = results&.map { _1.items.last }
|
270
|
+
end
|
271
|
+
|
272
|
+
attr_reader :key_name
|
273
|
+
attr_reader :value_name
|
274
|
+
attr_reader :iterable
|
275
|
+
attr_reader :body
|
276
|
+
|
277
|
+
def resolve_generator(context = nil)
|
278
|
+
@results ||= iterate_body(context)
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
def copy(parent = nil, position = @position)
|
283
|
+
if results
|
284
|
+
self.class.new(parent, key_name, value_name, nil, nil, copy_result, position)
|
285
|
+
else
|
286
|
+
copies = [iterable, body].map { _1&.copy }
|
287
|
+
self.class.new(parent, key_name, value_name, *copies, nil, position)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def collect_members(klass)
|
292
|
+
results
|
293
|
+
&.flat_map { collect_members_from_body(_1, klass) }
|
294
|
+
&.compact
|
295
|
+
end
|
296
|
+
|
297
|
+
private
|
298
|
+
|
299
|
+
attr_reader :results
|
300
|
+
|
301
|
+
def copy_result
|
302
|
+
results.map { _1.parent.copy }
|
303
|
+
end
|
304
|
+
|
305
|
+
ITERATION_METHODS = {
|
306
|
+
IntSeq => :iterate_intseq,
|
307
|
+
List => :iterate_collection,
|
308
|
+
Set => :iterate_collection,
|
309
|
+
Map => :iterate_map,
|
310
|
+
Listing => :iterate_listing,
|
311
|
+
Mapping => :iterate_mapping,
|
312
|
+
Dynamic => :iterate_dynamic
|
313
|
+
}.freeze
|
314
|
+
|
315
|
+
def iterate_body(context)
|
316
|
+
iterable_object = evaluate_iterable(context)
|
317
|
+
if (method = ITERATION_METHODS[iterable_object.class])
|
318
|
+
__send__(method, iterable_object)&.map do |(k, v)|
|
319
|
+
resolve_body(k, v)
|
320
|
+
end
|
321
|
+
else
|
322
|
+
message =
|
323
|
+
"cannot iterate over value of type '#{iterable_object.class_name}'"
|
324
|
+
raise EvaluationError.new(message, position)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def evaluate_iterable(context)
|
329
|
+
(context || current_context.pop).then do |c|
|
330
|
+
iterable.evaluate(c)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def iterate_intseq(intseq)
|
335
|
+
intseq.to_ruby.map.with_index do |v, i|
|
336
|
+
[Int.new(nil, i, nil), Int.new(nil, v, nil)]
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def iterate_collection(collection)
|
341
|
+
collection.elements.map.with_index do |e, i|
|
342
|
+
[Int.new(nil, i, nil), e]
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def iterate_map(map)
|
347
|
+
map.entries.map do |e|
|
348
|
+
[e.key, e.value]
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def iterate_listing(listing)
|
353
|
+
listing.elements&.map&.with_index do |e, i|
|
354
|
+
[Int.new(nil, i, nil), e.value]
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def iterate_mapping(mapping)
|
359
|
+
mapping.entries&.map do |e|
|
360
|
+
[e.key, e.value]
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def iterate_properties(dynamic)
|
365
|
+
dynamic.properties&.map do |p|
|
366
|
+
[String.new(nil, p.name.id.to_s, nil, nil), p.value]
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
def iterate_dynamic(dynamic)
|
371
|
+
[
|
372
|
+
*iterate_properties(dynamic),
|
373
|
+
*iterate_mapping(dynamic),
|
374
|
+
*iterate_listing(dynamic)
|
375
|
+
]
|
376
|
+
end
|
377
|
+
|
378
|
+
def resolve_body(key, value)
|
379
|
+
env = create_evaluation_env(key, value)
|
380
|
+
body
|
381
|
+
.copy(env)
|
382
|
+
.tap { _1.resolve_generator(_1.current_context) }
|
383
|
+
end
|
384
|
+
|
385
|
+
def create_evaluation_env(key, value)
|
386
|
+
iterators = []
|
387
|
+
iterators << create_iterator(key_name, key) if key_name
|
388
|
+
iterators << create_iterator(value_name, value)
|
389
|
+
ObjectBody.new(self, iterators, position)
|
390
|
+
end
|
391
|
+
|
392
|
+
def create_iterator(name, value)
|
393
|
+
ObjectProperty.new(nil, name, value, { local: true }, name.position)
|
394
|
+
end
|
395
|
+
|
396
|
+
def collect_members_from_body(body, klass)
|
397
|
+
body
|
398
|
+
.collect_members(klass)
|
399
|
+
&.tap { |members| check_no_properties(members, klass) }
|
400
|
+
end
|
401
|
+
|
402
|
+
def check_no_properties(members, klass)
|
403
|
+
return if members.empty? || klass != ObjectProperty
|
404
|
+
|
405
|
+
message = 'cannot generate object properties'
|
406
|
+
raise EvaluationError.new(message, position)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
189
410
|
class ObjectBody
|
190
411
|
include NodeCommon
|
191
412
|
include MemberFinder
|
192
413
|
|
193
|
-
def initialize(parent,
|
194
|
-
super(parent, position)
|
195
|
-
members&.each { add_member(_1) }
|
414
|
+
def initialize(parent, items, position)
|
415
|
+
super(parent, *items, position)
|
196
416
|
end
|
197
417
|
|
198
|
-
attr_reader :entries
|
199
|
-
attr_reader :elements
|
200
|
-
attr_reader :pkl_methods
|
201
418
|
attr_reader :pkl_classes
|
202
419
|
|
203
|
-
|
204
|
-
|
420
|
+
alias_method :items, :children
|
421
|
+
|
422
|
+
def properties(visibility: :lexical, all: false)
|
423
|
+
@properties ||= collect_members(ObjectProperty)
|
424
|
+
|
425
|
+
if all
|
205
426
|
@properties
|
206
|
-
|
427
|
+
elsif visibility == :lexical
|
428
|
+
@properties&.select { _1.visibility == :lexical || _1.parent.equal?(self) }
|
207
429
|
else
|
208
|
-
@properties
|
430
|
+
@properties&.select { !_1.local? }
|
209
431
|
end
|
210
432
|
end
|
211
433
|
|
212
|
-
def
|
213
|
-
|
434
|
+
def entries
|
435
|
+
@entries ||= collect_members(ObjectEntry)
|
436
|
+
end
|
437
|
+
|
438
|
+
def elements
|
439
|
+
@elements ||= collect_members(ObjectElement)
|
440
|
+
end
|
441
|
+
|
442
|
+
def pkl_methods
|
443
|
+
@pkl_methods ||= collect_members(MethodDefinition)
|
444
|
+
end
|
445
|
+
|
446
|
+
def fields(visibility: :lexical)
|
447
|
+
[*properties(visibility: visibility), *entries, *elements]
|
214
448
|
end
|
215
449
|
|
216
450
|
def definitions
|
217
451
|
[*pkl_methods, *pkl_classes]
|
218
452
|
end
|
219
453
|
|
220
|
-
def members
|
221
|
-
[*fields, *definitions]
|
454
|
+
def members(visibility: :lexical)
|
455
|
+
[*fields(visibility: visibility), *definitions]
|
222
456
|
end
|
223
457
|
|
224
458
|
def evaluate(context = nil)
|
@@ -226,11 +460,12 @@ module RuPkl
|
|
226
460
|
end
|
227
461
|
|
228
462
|
def resolve_structure(context = nil)
|
463
|
+
resolve_generator(context)
|
229
464
|
do_evaluation(__method__, context)
|
230
465
|
end
|
231
466
|
|
232
|
-
def copy(parent = nil)
|
233
|
-
copied_members =
|
467
|
+
def copy(parent = nil, position = @position)
|
468
|
+
copied_members = items&.map(&:copy)
|
234
469
|
self.class.new(parent, copied_members, position)
|
235
470
|
end
|
236
471
|
|
@@ -238,6 +473,17 @@ module RuPkl
|
|
238
473
|
super&.push_scope(self)
|
239
474
|
end
|
240
475
|
|
476
|
+
def resolve_generator(context = nil)
|
477
|
+
generators&.each { _1.resolve_generator(context) }
|
478
|
+
self
|
479
|
+
end
|
480
|
+
|
481
|
+
def collect_members(klass)
|
482
|
+
items
|
483
|
+
&.each_with_object([], &member_collector(klass))
|
484
|
+
&.then { !_1.empty? && _1 || nil }
|
485
|
+
end
|
486
|
+
|
241
487
|
def merge!(*others)
|
242
488
|
others.each { do_merge(_1) }
|
243
489
|
self
|
@@ -245,58 +491,68 @@ module RuPkl
|
|
245
491
|
|
246
492
|
private
|
247
493
|
|
248
|
-
|
249
|
-
|
494
|
+
GENERATOR_CLASSES = [
|
495
|
+
WhenGenerator,
|
496
|
+
ForGenerator
|
497
|
+
].freeze
|
250
498
|
|
251
|
-
|
252
|
-
|
253
|
-
instance_variable_set(varialbe_name, [])
|
254
|
-
end
|
255
|
-
instance_variable_get(varialbe_name) << member
|
499
|
+
def generator?(item)
|
500
|
+
GENERATOR_CLASSES.any? { item.is_a?(_1) }
|
256
501
|
end
|
257
502
|
|
258
|
-
def
|
259
|
-
{
|
260
|
-
ObjectProperty => :@properties,
|
261
|
-
ObjectEntry => :@entries,
|
262
|
-
ObjectElement => :@elements,
|
263
|
-
MethodDefinition => :@pkl_methods
|
264
|
-
}[member.class]
|
503
|
+
def generators
|
504
|
+
items&.select { generator?(_1) }
|
265
505
|
end
|
266
506
|
|
267
507
|
def do_evaluation(evaluator, context)
|
268
508
|
(context&.push_scope(self) || current_context).then do |c|
|
269
|
-
fields
|
509
|
+
fields&.each do |field|
|
510
|
+
if field.generated?
|
511
|
+
field.__send__(evaluator)
|
512
|
+
else
|
513
|
+
field.__send__(evaluator, c)
|
514
|
+
end
|
515
|
+
end
|
270
516
|
check_duplication
|
271
517
|
self
|
272
518
|
end
|
273
519
|
end
|
274
520
|
|
275
521
|
def check_duplication
|
276
|
-
check_duplication_members(
|
277
|
-
check_duplication_members(
|
278
|
-
check_duplication_members(
|
522
|
+
check_duplication_members(properties(all: true))
|
523
|
+
check_duplication_members(entries)
|
524
|
+
check_duplication_members(pkl_methods)
|
279
525
|
end
|
280
526
|
|
281
|
-
def check_duplication_members(members
|
527
|
+
def check_duplication_members(members)
|
282
528
|
members&.each do |member|
|
283
|
-
duplicate_member?(members, member
|
529
|
+
duplicate_member?(members, member) &&
|
284
530
|
(raise EvaluationError.new('duplicate definition of member', member.position))
|
285
531
|
end
|
286
532
|
end
|
287
533
|
|
288
|
-
def duplicate_member?(members, member
|
289
|
-
count =
|
290
|
-
members
|
291
|
-
.count { _1.__send__(accessor) == member.__send__(accessor) }
|
534
|
+
def duplicate_member?(members, member)
|
535
|
+
count = members.count { !_1.coexistable?(member) }
|
292
536
|
count > 1
|
293
537
|
end
|
294
538
|
|
539
|
+
def member_collector(klass)
|
540
|
+
proc do |item, members|
|
541
|
+
if generator?(item)
|
542
|
+
items = item.collect_members(klass)
|
543
|
+
items && members.concat(items.each { _1.generated = true })
|
544
|
+
elsif item.is_a?(klass)
|
545
|
+
members << item
|
546
|
+
end
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
295
550
|
def do_merge(rhs)
|
551
|
+
rhs_properties = rhs.properties(visibility: :object)
|
296
552
|
rhs_entries, rhs_amend = split_entries(rhs.entries)
|
297
|
-
@properties = merge_hash_members(
|
298
|
-
@entries = merge_hash_members(
|
299
|
-
@elements = merge_array_members(
|
553
|
+
@properties = merge_hash_members(properties(all: true), rhs_properties)
|
554
|
+
@entries = merge_hash_members(entries, rhs_entries)
|
555
|
+
@elements = merge_array_members(elements, rhs.elements, rhs_amend, :key)
|
300
556
|
end
|
301
557
|
|
302
558
|
def split_entries(entries)
|
@@ -313,12 +569,12 @@ module RuPkl
|
|
313
569
|
node.instance_of?(Node::Int) && node.value < elements_size
|
314
570
|
end
|
315
571
|
|
316
|
-
def merge_hash_members(lhs, rhs
|
572
|
+
def merge_hash_members(lhs, rhs)
|
317
573
|
return nil unless lhs || rhs
|
318
574
|
return rhs unless lhs
|
319
575
|
|
320
576
|
rhs&.each do |r|
|
321
|
-
if (index = find_member_index(lhs, r
|
577
|
+
if (index = find_member_index(lhs, r))
|
322
578
|
lhs[index] = merge_hash_value(lhs[index], r)
|
323
579
|
else
|
324
580
|
r.visibility = :object
|
@@ -331,15 +587,15 @@ module RuPkl
|
|
331
587
|
|
332
588
|
def merge_hash_value(lhs, rhs)
|
333
589
|
if [lhs.value, rhs.value].all? { _1.respond_to?(:body) }
|
334
|
-
lhs.value.merge!(rhs.value)
|
590
|
+
lhs.value.merge!(rhs.value.body)
|
335
591
|
lhs
|
336
592
|
else
|
337
593
|
rhs
|
338
594
|
end
|
339
595
|
end
|
340
596
|
|
341
|
-
def find_member_index(lhs, rhs
|
342
|
-
lhs.find_index { _1.
|
597
|
+
def find_member_index(lhs, rhs)
|
598
|
+
lhs.find_index { !_1.coexistable?(rhs) }
|
343
599
|
end
|
344
600
|
|
345
601
|
def merge_array_members(lhs_array, rhs_array, rhs_hash, accessor)
|
@@ -398,7 +654,7 @@ module RuPkl
|
|
398
654
|
true
|
399
655
|
end
|
400
656
|
|
401
|
-
def copy(parent = nil)
|
657
|
+
def copy(parent = nil, position = @position)
|
402
658
|
self.class.new(parent, type, bodies, position)
|
403
659
|
end
|
404
660
|
|