rupkl 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/rupkl/node/amend_expression.rb +48 -0
- data/lib/rupkl/node/any.rb +99 -0
- data/lib/rupkl/node/base.rb +45 -0
- data/lib/rupkl/node/boolean.rb +12 -4
- data/lib/rupkl/node/context.rb +27 -0
- data/lib/rupkl/node/declared_type.rb +32 -0
- data/lib/rupkl/node/dynamic.rb +28 -59
- data/lib/rupkl/node/identifier.rb +16 -6
- data/lib/rupkl/node/listing.rb +61 -0
- data/lib/rupkl/node/mapping.rb +47 -0
- data/lib/rupkl/node/member_finder.rb +55 -0
- data/lib/rupkl/node/member_reference.rb +44 -21
- data/lib/rupkl/node/method_call.rb +64 -0
- data/lib/rupkl/node/method_definition.rb +143 -0
- data/lib/rupkl/node/node_common.rb +76 -0
- data/lib/rupkl/node/null.rb +27 -0
- data/lib/rupkl/node/number.rb +136 -6
- data/lib/rupkl/node/object.rb +369 -73
- data/lib/rupkl/node/operation.rb +97 -60
- data/lib/rupkl/node/pkl_module.rb +16 -28
- data/lib/rupkl/node/reference_resolver.rb +79 -0
- data/lib/rupkl/node/string.rb +388 -18
- data/lib/rupkl/node/struct_common.rb +119 -57
- data/lib/rupkl/node/this.rb +17 -0
- data/lib/rupkl/node/type_common.rb +34 -0
- data/lib/rupkl/node/value_common.rb +18 -9
- data/lib/rupkl/parser/expression.rb +158 -41
- data/lib/rupkl/parser/identifier.rb +2 -2
- data/lib/rupkl/parser/literal.rb +18 -12
- data/lib/rupkl/parser/method.rb +41 -0
- data/lib/rupkl/parser/misc.rb +4 -0
- data/lib/rupkl/parser/object.rb +57 -25
- data/lib/rupkl/parser/pkl_class.rb +28 -8
- data/lib/rupkl/parser/pkl_module.rb +5 -3
- data/lib/rupkl/parser/type.rb +28 -0
- data/lib/rupkl/parser.rb +8 -0
- data/lib/rupkl/pkl_object.rb +26 -6
- data/lib/rupkl/version.rb +1 -1
- data/lib/rupkl.rb +25 -4
- metadata +33 -3
- data/lib/rupkl/node/pkl_class.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7731a56bb62b392639860c5e0f82c2175e8bca4ecd439e8ccffd05d9b223b0f
|
4
|
+
data.tar.gz: 18487cb107c5a47212d185d782f4866d5fc5c0734b893986e4388c003728687d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9d8c2d0d8d9f4976ba804810285344b8f5a6cd308ce1eeff23eb3503feb365c2415d1876c8c879fdf38ca016b01dc849aaeb2e01ae502b9c0e0a44a1a2123ce
|
7
|
+
data.tar.gz: 2bc34ee5b570519a913299dbe5415fe9a7e3dd406b5912f729127ce152c18fd6821f769f9c6df6e677c0c114de935f401584e67e5ae385133aef318810f57ce0
|
data/README.md
CHANGED
@@ -116,7 +116,7 @@ Pkl code snippets used for RSpec examples are originaly from:
|
|
116
116
|
## Copyright & License
|
117
117
|
|
118
118
|
Copyright © 2024 Taichi Ishitani.
|
119
|
-
RuPkl is licensed under the terms of the [MIT License](https://opensource.org/licenses/MIT), see [LICENSE](LICENSE) for further details.
|
119
|
+
RuPkl is licensed under the terms of the [MIT License](https://opensource.org/licenses/MIT), see [LICENSE.txt](LICENSE.txt) for further details.
|
120
120
|
|
121
121
|
## Code of Conduct
|
122
122
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class AmendExpression
|
6
|
+
include NodeCommon
|
7
|
+
|
8
|
+
def initialize(parent, target, bodies, position)
|
9
|
+
super(parent, target, *bodies, position)
|
10
|
+
@target = target
|
11
|
+
@bodies = bodies
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :target
|
15
|
+
attr_reader :bodies
|
16
|
+
|
17
|
+
def evaluate(context = nil)
|
18
|
+
resolve_structure(context).evaluate(context)
|
19
|
+
end
|
20
|
+
|
21
|
+
def resolve_structure(context = nil)
|
22
|
+
t =
|
23
|
+
target
|
24
|
+
.resolve_reference(context)
|
25
|
+
.resolve_structure(context)
|
26
|
+
t.respond_to?(:body) ||
|
27
|
+
begin
|
28
|
+
message = "cannot amend the target type #{t.class.basename}"
|
29
|
+
raise EvaluationError.new(message, position)
|
30
|
+
end
|
31
|
+
do_amend(t.copy(parent))
|
32
|
+
end
|
33
|
+
|
34
|
+
def copy(parent = nil)
|
35
|
+
self.class.new(parent, target.copy, bodies.each(&:copy), position)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def do_amend(target)
|
41
|
+
bodies
|
42
|
+
.map { _1.copy(target).resolve_structure }
|
43
|
+
.then { target.merge!(*_1) }
|
44
|
+
target
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Any
|
6
|
+
include NodeCommon
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def abstract?
|
10
|
+
@abstract || false
|
11
|
+
end
|
12
|
+
|
13
|
+
def instantiable?
|
14
|
+
!@uninstantiable
|
15
|
+
end
|
16
|
+
|
17
|
+
def class_name
|
18
|
+
@class_name || basename.to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def builtin_property(name)
|
22
|
+
@builtin_properties&.[](name.id)
|
23
|
+
end
|
24
|
+
|
25
|
+
def buildin_method(name)
|
26
|
+
@builtin_methods&.[](name.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def abstract_class
|
32
|
+
@abstract = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def uninstantiable_class
|
36
|
+
@uninstantiable = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def klass_name(name)
|
40
|
+
@class_name = name
|
41
|
+
end
|
42
|
+
|
43
|
+
def define_builtin_property(name, &body)
|
44
|
+
(@builtin_properties ||= {})[name] = body
|
45
|
+
end
|
46
|
+
|
47
|
+
def define_builtin_method(name, ...)
|
48
|
+
(@builtin_methods ||= {})[name] = BuiltinMethodDefinition.new(name, ...)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
abstract_class
|
53
|
+
uninstantiable_class
|
54
|
+
|
55
|
+
def property(name)
|
56
|
+
builtin_property(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pkl_method(name)
|
60
|
+
buildin_method(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def null?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def builtin_property(name)
|
70
|
+
self.class.ancestors.each do |klass|
|
71
|
+
next unless klass.respond_to?(:builtin_property)
|
72
|
+
|
73
|
+
body = klass.builtin_property(name)
|
74
|
+
return instance_exec(&body) if body
|
75
|
+
end
|
76
|
+
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def buildin_method(name)
|
81
|
+
self.class.ancestors.each do |klass|
|
82
|
+
next unless klass.respond_to?(:buildin_method)
|
83
|
+
|
84
|
+
method = klass.buildin_method(name)
|
85
|
+
return method if method
|
86
|
+
end
|
87
|
+
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_positive_number(number)
|
92
|
+
return unless number.value.negative?
|
93
|
+
|
94
|
+
m = "expected a positive number, but got '#{number.value}'"
|
95
|
+
raise EvaluationError.new(m, position)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Base < PklModule
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(nil, nil, nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :pkl_classes
|
13
|
+
|
14
|
+
class << self
|
15
|
+
private
|
16
|
+
|
17
|
+
def add_builtin_class(klass)
|
18
|
+
instance.instance_eval do
|
19
|
+
name = klass.class_name
|
20
|
+
(@pkl_classes ||= {})[name] = klass
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
add_builtin_class Any
|
26
|
+
add_builtin_class Boolean
|
27
|
+
add_builtin_class Number
|
28
|
+
add_builtin_class Int
|
29
|
+
add_builtin_class Float
|
30
|
+
add_builtin_class String
|
31
|
+
add_builtin_class Dynamic
|
32
|
+
add_builtin_class Mapping
|
33
|
+
add_builtin_class Listing
|
34
|
+
add_builtin_class PklModule
|
35
|
+
|
36
|
+
define_builtin_property(:NaN) do
|
37
|
+
Float.new(parent, ::Float::NAN, position)
|
38
|
+
end
|
39
|
+
|
40
|
+
define_builtin_property(:Infinity) do
|
41
|
+
Float.new(parent, ::Float::INFINITY, position)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/rupkl/node/boolean.rb
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
|
-
class Boolean
|
5
|
+
class Boolean < Any
|
6
6
|
include ValueCommon
|
7
7
|
|
8
|
-
|
9
|
-
self
|
10
|
-
end
|
8
|
+
uninstantiable_class
|
11
9
|
|
12
10
|
def undefined_operator?(operator)
|
13
11
|
[:!, :==, :'!=', :'&&', :'||'].none?(operator)
|
@@ -16,6 +14,16 @@ module RuPkl
|
|
16
14
|
def short_circuit?(operator)
|
17
15
|
[operator, value] in [:'&&', false] | [:'||', true]
|
18
16
|
end
|
17
|
+
|
18
|
+
define_builtin_method(:xor, other: Boolean) do |other|
|
19
|
+
result = value ^ other.value
|
20
|
+
Boolean.new(nil, result, position)
|
21
|
+
end
|
22
|
+
|
23
|
+
define_builtin_method(:implies, other: Boolean) do |other|
|
24
|
+
result = !value || other.value
|
25
|
+
Boolean.new(nil, result, position)
|
26
|
+
end
|
19
27
|
end
|
20
28
|
end
|
21
29
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Context
|
6
|
+
def initialize(scopes, objects)
|
7
|
+
@scopes = scopes
|
8
|
+
@objects = objects
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :scopes
|
12
|
+
attr_reader :objects
|
13
|
+
|
14
|
+
def push_scope(scope)
|
15
|
+
Context.new([*scopes, scope], objects)
|
16
|
+
end
|
17
|
+
|
18
|
+
def push_object(object)
|
19
|
+
Context.new(scopes, [*objects, object])
|
20
|
+
end
|
21
|
+
|
22
|
+
def pop
|
23
|
+
Context.new(scopes&.slice(..-2), objects&.slice(..-2))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class DeclaredType
|
6
|
+
include TypeCommon
|
7
|
+
|
8
|
+
def initialize(parent, type, position)
|
9
|
+
super(parent, *type, position)
|
10
|
+
@type = type
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
def find_class(context)
|
16
|
+
find_type(type, context)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
type.last.id.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def match_type?(klass, context)
|
26
|
+
rhs = klass
|
27
|
+
lhs = find_class(context)
|
28
|
+
rhs <= lhs
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/rupkl/node/dynamic.rb
CHANGED
@@ -2,36 +2,19 @@
|
|
2
2
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
|
-
class Dynamic
|
5
|
+
class Dynamic < Any
|
6
6
|
include StructCommon
|
7
7
|
|
8
|
-
def
|
9
|
-
@
|
10
|
-
add_members(members, scopes)
|
8
|
+
def properties
|
9
|
+
@body&.properties(visibility: :object)
|
11
10
|
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :elements
|
16
|
-
attr_reader :position
|
17
|
-
|
18
|
-
def evaluate(_scopes)
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_ruby(_scopes)
|
23
|
-
create_pkl_object(nil, properties, entries, elements)
|
12
|
+
def entries
|
13
|
+
@body&.entries
|
24
14
|
end
|
25
15
|
|
26
|
-
def
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def merge!(other)
|
31
|
-
@properties = merge_hash_members(properties, other.properties, :name)
|
32
|
-
@entries = merge_hash_members(entries, other.entries, :key)
|
33
|
-
@elements = merge_array_members(elements, other.elements)
|
34
|
-
self
|
16
|
+
def elements
|
17
|
+
@body&.elements
|
35
18
|
end
|
36
19
|
|
37
20
|
def ==(other)
|
@@ -41,58 +24,44 @@ module RuPkl
|
|
41
24
|
match_members?(elements, other.elements, true)
|
42
25
|
end
|
43
26
|
|
44
|
-
def undefined_operator?(operator)
|
45
|
-
[:[], :==, :'!='].none?(operator)
|
46
|
-
end
|
47
|
-
|
48
27
|
def find_by_key(key)
|
49
28
|
find_entry(key) || find_element(key)
|
50
29
|
end
|
51
30
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
31
|
+
define_builtin_method(:length) do
|
32
|
+
result = elements&.size || 0
|
33
|
+
Int.new(nil, result, position)
|
34
|
+
end
|
56
35
|
|
57
|
-
|
58
|
-
|
59
|
-
|
36
|
+
define_builtin_method(:hasProperty, name: String) do |name|
|
37
|
+
result = find_property(name.value.to_sym) && true || false
|
38
|
+
Boolean.new(nil, result, position)
|
60
39
|
end
|
61
40
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
else add_element(m)
|
41
|
+
define_builtin_method(:getProperty, name: String) do |name|
|
42
|
+
find_property(name.value.to_sym) ||
|
43
|
+
begin
|
44
|
+
m = "cannot find property '#{name.value}'"
|
45
|
+
raise EvaluationError.new(m, position)
|
68
46
|
end
|
69
|
-
end
|
70
47
|
end
|
71
48
|
|
72
|
-
|
73
|
-
|
49
|
+
define_builtin_method(:getPropertyOrNull, name: String) do |name|
|
50
|
+
find_property(name.value.to_sym) || Null.new(nil, position)
|
74
51
|
end
|
75
52
|
|
76
|
-
|
77
|
-
add_hash_member((@entries ||= []), member, :key)
|
78
|
-
end
|
53
|
+
private
|
79
54
|
|
80
|
-
def
|
81
|
-
|
55
|
+
def properties_not_allowed?
|
56
|
+
false
|
82
57
|
end
|
83
58
|
|
84
|
-
def
|
85
|
-
|
86
|
-
&.find { _1.key == key }
|
87
|
-
&.then(&:value)
|
59
|
+
def entries_not_allowed?
|
60
|
+
false
|
88
61
|
end
|
89
62
|
|
90
|
-
def
|
91
|
-
|
92
|
-
return nil unless index.value.is_a?(::Integer)
|
93
|
-
|
94
|
-
elements
|
95
|
-
.find.with_index { |_, i| i == index.value }
|
63
|
+
def elements_not_allowed?
|
64
|
+
false
|
96
65
|
end
|
97
66
|
end
|
98
67
|
end
|
@@ -3,17 +3,27 @@
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
5
|
class Identifier
|
6
|
-
|
6
|
+
include NodeCommon
|
7
|
+
|
8
|
+
def initialize(parent, id, position)
|
9
|
+
super(parent, position)
|
7
10
|
@id = id
|
8
|
-
@position = position
|
9
11
|
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
attr_reader :id
|
14
|
+
|
15
|
+
def copy(parent = nil)
|
16
|
+
self.class.new(parent, id, position)
|
13
17
|
end
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
def ==(other)
|
20
|
+
id ==
|
21
|
+
if other.respond_to?(:id)
|
22
|
+
other.id
|
23
|
+
else
|
24
|
+
other
|
25
|
+
end
|
26
|
+
end
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Listing < Any
|
6
|
+
include StructCommon
|
7
|
+
|
8
|
+
def elements
|
9
|
+
@body&.elements
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
other.instance_of?(self.class) &&
|
14
|
+
match_members?(elements, other.elements, true)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_by_key(key)
|
18
|
+
find_element(key)
|
19
|
+
end
|
20
|
+
|
21
|
+
define_builtin_property(:isEmpty) do
|
22
|
+
result = elements.nil? || elements.empty?
|
23
|
+
Boolean.new(self, result, position)
|
24
|
+
end
|
25
|
+
|
26
|
+
define_builtin_property(:length) do
|
27
|
+
result = elements&.size || 0
|
28
|
+
Int.new(self, result, position)
|
29
|
+
end
|
30
|
+
|
31
|
+
define_builtin_property(:isDistinct) do
|
32
|
+
result =
|
33
|
+
elements.nil? ||
|
34
|
+
elements.all? { |lhs| elements.one? { |rhs| rhs == lhs } }
|
35
|
+
Boolean.new(self, result || elements.nil?, position)
|
36
|
+
end
|
37
|
+
|
38
|
+
define_builtin_property(:distinct) do
|
39
|
+
result =
|
40
|
+
elements
|
41
|
+
&.each_with_object([]) { |e, l| l << e unless l.include?(e) }
|
42
|
+
body = ObjectBody.new(nil, result, position)
|
43
|
+
Listing.new(self, body, position)
|
44
|
+
end
|
45
|
+
|
46
|
+
define_builtin_method(:join, separator: String) do |separator|
|
47
|
+
result =
|
48
|
+
elements
|
49
|
+
&.map { _1.value.to_string }
|
50
|
+
&.join(separator.value)
|
51
|
+
String.new(nil, result || '', nil, position)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def elements_not_allowed?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Mapping < Any
|
6
|
+
include StructCommon
|
7
|
+
|
8
|
+
def entries
|
9
|
+
@body&.entries
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
other.instance_of?(self.class) &&
|
14
|
+
match_members?(entries, other.entries, false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_by_key(key)
|
18
|
+
find_entry(key)
|
19
|
+
end
|
20
|
+
|
21
|
+
define_builtin_property(:isEmpty) do
|
22
|
+
result = entries.nil? || entries.empty?
|
23
|
+
Boolean.new(self, result, position)
|
24
|
+
end
|
25
|
+
|
26
|
+
define_builtin_property(:length) do
|
27
|
+
result = entries&.size || 0
|
28
|
+
Int.new(self, result, position)
|
29
|
+
end
|
30
|
+
|
31
|
+
define_builtin_method(:containsKey, key: Any) do |key|
|
32
|
+
result = find_entry(key) && true || false
|
33
|
+
Boolean.new(nil, result, position)
|
34
|
+
end
|
35
|
+
|
36
|
+
define_builtin_method(:getOrNull, key: Any) do |key|
|
37
|
+
find_entry(key) || Null.new(nil, position)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def entries_not_allowed?
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
module MemberFinder
|
6
|
+
def property(name)
|
7
|
+
value = find_property(name)
|
8
|
+
return value if value
|
9
|
+
|
10
|
+
super if self.class <= Any
|
11
|
+
end
|
12
|
+
|
13
|
+
def pkl_method(name)
|
14
|
+
method = find_pkl_method(name)
|
15
|
+
return method if method
|
16
|
+
|
17
|
+
super if self.class <= Any
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def find_property(name)
|
23
|
+
return unless respond_to?(:properties)
|
24
|
+
|
25
|
+
properties
|
26
|
+
&.find { _1.name == name }
|
27
|
+
&.value
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_entry(key)
|
31
|
+
return unless respond_to?(:entries)
|
32
|
+
|
33
|
+
entries
|
34
|
+
&.find { _1.key == key }
|
35
|
+
&.value
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_element(index)
|
39
|
+
return unless respond_to?(:elements)
|
40
|
+
return unless elements
|
41
|
+
return unless index.value.is_a?(::Integer)
|
42
|
+
|
43
|
+
elements
|
44
|
+
.find.with_index { |_, i| i == index.value }
|
45
|
+
&.value
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_pkl_method(name)
|
49
|
+
return unless respond_to?(:pkl_methods)
|
50
|
+
|
51
|
+
pkl_methods&.find { _1.name == name }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|