rupkl 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|