rupkl 0.1.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/README.md +1 -1
- data/lib/rupkl/node/amend_expression.rb +48 -0
- data/lib/rupkl/node/any.rb +110 -0
- data/lib/rupkl/node/base.rb +75 -0
- data/lib/rupkl/node/boolean.rb +30 -5
- data/lib/rupkl/node/collection.rb +176 -0
- data/lib/rupkl/node/context.rb +27 -0
- data/lib/rupkl/node/data_size.rb +254 -0
- data/lib/rupkl/node/declared_type.rb +32 -0
- data/lib/rupkl/node/duration.rb +266 -0
- data/lib/rupkl/node/dynamic.rb +33 -60
- data/lib/rupkl/node/identifier.rb +19 -5
- data/lib/rupkl/node/if_expression.rb +45 -0
- data/lib/rupkl/node/intseq.rb +84 -0
- data/lib/rupkl/node/listing.rb +68 -0
- data/lib/rupkl/node/map.rb +120 -0
- data/lib/rupkl/node/mapping.rb +54 -0
- data/lib/rupkl/node/member_finder.rb +49 -0
- data/lib/rupkl/node/member_reference.rb +46 -21
- data/lib/rupkl/node/method_call.rb +63 -0
- data/lib/rupkl/node/method_definition.rb +199 -0
- data/lib/rupkl/node/node_common.rb +76 -0
- data/lib/rupkl/node/null.rb +24 -0
- data/lib/rupkl/node/number.rb +228 -10
- data/lib/rupkl/node/object.rb +626 -74
- data/lib/rupkl/node/operation.rb +175 -115
- data/lib/rupkl/node/pair.rb +58 -0
- data/lib/rupkl/node/pkl_module.rb +16 -28
- data/lib/rupkl/node/reference_resolver.rb +79 -0
- data/lib/rupkl/node/regex.rb +196 -0
- data/lib/rupkl/node/string.rb +415 -23
- data/lib/rupkl/node/struct_common.rb +150 -53
- 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 -13
- data/lib/rupkl/parser/expression.rb +197 -43
- 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 +24 -0
- data/lib/rupkl/parser/object.rb +141 -26
- data/lib/rupkl/parser/pkl_class.rb +37 -10
- 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 +11 -7
- data/lib/rupkl/version.rb +1 -1
- data/lib/rupkl.rb +35 -6
- metadata +45 -7
- data/lib/rupkl/node/pkl_class.rb +0 -30
data/lib/rupkl/node/operation.rb
CHANGED
@@ -2,184 +2,244 @@
|
|
2
2
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
|
-
module
|
6
|
-
def
|
7
|
-
|
5
|
+
module Operatable
|
6
|
+
def s_op(operator, key, context, position)
|
7
|
+
check_s_op(operator, position)
|
8
|
+
|
9
|
+
k = key.evaluate(context)
|
10
|
+
valid_key_operand?(k) ||
|
11
|
+
raise_invalid_key_error(operator, k, position)
|
12
|
+
|
13
|
+
(v = find_by_key(k)) ||
|
14
|
+
raise_no_key_found_error(k, context, position)
|
15
|
+
|
16
|
+
v.evaluate
|
8
17
|
end
|
9
18
|
|
10
|
-
def
|
11
|
-
|
19
|
+
def u_op(operator, position)
|
20
|
+
check_u_op(operator, position)
|
21
|
+
__send__(u_op_method(operator), position)
|
12
22
|
end
|
13
23
|
|
14
|
-
def
|
15
|
-
|
24
|
+
def b_op(operator, operand, context, position)
|
25
|
+
check_b_op(operator, position)
|
26
|
+
return self if short_circuit?(operator)
|
27
|
+
|
28
|
+
r_operand = operand.evaluate(context)
|
29
|
+
if valid_r_operand?(operator, r_operand)
|
30
|
+
__send__(b_op_method(operator), r_operand, position)
|
31
|
+
elsif [:==, :'!='].any?(operator)
|
32
|
+
Boolean.new(nil, operator != :==, position)
|
33
|
+
else
|
34
|
+
raise_invalid_r_operand_error(operator, r_operand, position)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def b_op_eq(r_operand, position)
|
39
|
+
result = self == r_operand
|
40
|
+
Boolean.new(nil, result, position)
|
41
|
+
end
|
42
|
+
|
43
|
+
def b_op_ne(r_operand, position)
|
44
|
+
result = self != r_operand
|
45
|
+
Boolean.new(nil, result, position)
|
16
46
|
end
|
17
47
|
|
18
48
|
private
|
19
49
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
50
|
+
def check_s_op(operator, position)
|
51
|
+
check_operator(operator, position)
|
52
|
+
end
|
23
53
|
|
24
|
-
|
25
|
-
|
54
|
+
def valid_key_operand?(_key)
|
55
|
+
true
|
56
|
+
end
|
26
57
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
58
|
+
def raise_invalid_key_error(operator, key, position)
|
59
|
+
message =
|
60
|
+
"invalid key operand type #{key.class_name} is given " \
|
61
|
+
"for operator '#{operator}'"
|
62
|
+
raise EvaluationError.new(message, position)
|
32
63
|
end
|
33
64
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
65
|
+
def raise_no_key_found_error(key, context, position)
|
66
|
+
message = "cannot find key '#{key.to_pkl_string(context)}'"
|
67
|
+
raise EvaluationError.new(message, position)
|
68
|
+
end
|
37
69
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
else
|
42
|
-
!o.value
|
43
|
-
end
|
44
|
-
create_op_result(result)
|
70
|
+
def check_u_op(operator, position)
|
71
|
+
op = :"#{operator}@"
|
72
|
+
check_operator(op, position)
|
45
73
|
end
|
46
74
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
return l if short_circuit?(l)
|
75
|
+
def u_op_method(operator)
|
76
|
+
{ '-': :u_op_minus, '!': :u_op_negate }[operator]
|
77
|
+
end
|
51
78
|
|
52
|
-
|
53
|
-
|
79
|
+
def check_b_op(operator, position)
|
80
|
+
check_operator(operator, position)
|
81
|
+
end
|
54
82
|
|
55
|
-
|
56
|
-
|
83
|
+
def short_circuit?(_operator)
|
84
|
+
false
|
57
85
|
end
|
58
86
|
|
59
|
-
def
|
60
|
-
|
61
|
-
begin
|
62
|
-
message =
|
63
|
-
"operator '#{operator}' is not defined for " \
|
64
|
-
"#{operand.class.basename} type"
|
65
|
-
raise EvaluationError.new(message, position)
|
66
|
-
end
|
87
|
+
def valid_r_operand?(_operator, operand)
|
88
|
+
operand.is_a?(self.class)
|
67
89
|
end
|
68
90
|
|
69
|
-
def
|
70
|
-
|
71
|
-
operand.
|
91
|
+
def raise_invalid_r_operand_error(operator, r_operand, position)
|
92
|
+
message =
|
93
|
+
"invalid operand type #{r_operand.class_name} is given " \
|
94
|
+
"for operator '#{operator}'"
|
95
|
+
raise EvaluationError.new(message, position)
|
72
96
|
end
|
73
97
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
98
|
+
def b_op_method(operator)
|
99
|
+
{
|
100
|
+
'**': :b_op_exp,
|
101
|
+
'*': :b_op_mul, '/': :b_op_div,
|
102
|
+
'~/': :b_op_truncating_div, '%': :b_op_rem,
|
103
|
+
'+': :b_op_add, '-': :b_op_sub,
|
104
|
+
'<': :b_op_lt, '>': :b_op_gt,
|
105
|
+
'<=': :b_op_le, '>=': :b_op_ge,
|
106
|
+
'==': :b_op_eq, '!=': :b_op_ne,
|
107
|
+
'&&': :b_op_and, '||': :b_op_or
|
108
|
+
}[operator]
|
82
109
|
end
|
83
110
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
111
|
+
def check_operator(operator, position)
|
112
|
+
return if
|
113
|
+
[:==, :'!='].any?(operator) || defined_operator?(operator)
|
114
|
+
|
115
|
+
message = "operator '#{operator}' is not defined for #{class_name} type"
|
116
|
+
raise EvaluationError.new(message, position)
|
87
117
|
end
|
88
118
|
|
89
|
-
def
|
90
|
-
|
91
|
-
begin
|
92
|
-
message =
|
93
|
-
"invalid operand type #{r_operand.class.basename} is given " \
|
94
|
-
"for operator '#{operator}'"
|
95
|
-
raise EvaluationError.new(message, position)
|
96
|
-
end
|
119
|
+
def defined_operator?(_operator)
|
120
|
+
false
|
97
121
|
end
|
122
|
+
end
|
98
123
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
124
|
+
module OperationCommon
|
125
|
+
include NodeCommon
|
126
|
+
|
127
|
+
def initialize(parent, operator, *operands, position)
|
128
|
+
super(parent, *operands, position)
|
129
|
+
@operator = operator
|
130
|
+
@operands = operands
|
105
131
|
end
|
106
132
|
|
107
|
-
|
108
|
-
|
109
|
-
|
133
|
+
attr_reader :operator
|
134
|
+
attr_reader :operands
|
135
|
+
|
136
|
+
def copy(parent = nil, position = @position)
|
137
|
+
copied_operands = operands.map(&:copy)
|
138
|
+
self.class.new(parent, operator, *copied_operands, position)
|
110
139
|
end
|
111
140
|
|
112
|
-
|
113
|
-
|
141
|
+
private
|
142
|
+
|
143
|
+
def s_op(context)
|
144
|
+
r = receiver.evaluate(context)
|
145
|
+
r.s_op(operator, key, context, position)
|
114
146
|
end
|
115
147
|
|
116
|
-
def
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
148
|
+
def non_null_op(context)
|
149
|
+
o = operand.evaluate(context)
|
150
|
+
return o unless o.null?
|
151
|
+
|
152
|
+
m = "expected a non-null value but got '#{o.to_pkl_string(context)}'"
|
153
|
+
raise EvaluationError.new(m, position)
|
154
|
+
end
|
155
|
+
|
156
|
+
def u_op(context)
|
157
|
+
o = operand.evaluate(context)
|
158
|
+
o.u_op(operator, position)
|
159
|
+
end
|
160
|
+
|
161
|
+
def b_op(context)
|
162
|
+
l = l_operand.evaluate(context)
|
163
|
+
l.b_op(operator, r_operand, context, position)
|
164
|
+
end
|
165
|
+
|
166
|
+
def null_coalescing_op(context)
|
167
|
+
l = l_operand.evaluate(context)
|
168
|
+
return l unless l.null?
|
169
|
+
|
170
|
+
r_operand.evaluate(context)
|
123
171
|
end
|
124
172
|
end
|
125
173
|
|
126
174
|
class SubscriptOperation
|
127
175
|
include OperationCommon
|
128
176
|
|
129
|
-
def
|
130
|
-
|
131
|
-
@key = key
|
132
|
-
@position = position
|
177
|
+
def receiver
|
178
|
+
operands.first
|
133
179
|
end
|
134
180
|
|
135
|
-
|
136
|
-
|
137
|
-
|
181
|
+
def key
|
182
|
+
operands.last
|
183
|
+
end
|
138
184
|
|
139
|
-
def
|
140
|
-
|
185
|
+
def evaluate(context = nil)
|
186
|
+
s_op(context)
|
141
187
|
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class NonNullOperation
|
191
|
+
include OperationCommon
|
142
192
|
|
143
|
-
def
|
144
|
-
|
193
|
+
def operand
|
194
|
+
operands.first
|
195
|
+
end
|
196
|
+
|
197
|
+
def evaluate(context = nil)
|
198
|
+
non_null_op(context)
|
145
199
|
end
|
146
200
|
end
|
147
201
|
|
148
202
|
class UnaryOperation
|
149
203
|
include OperationCommon
|
150
204
|
|
151
|
-
def
|
152
|
-
|
153
|
-
@operand = operand
|
154
|
-
@position = position
|
205
|
+
def operand
|
206
|
+
operands.first
|
155
207
|
end
|
156
208
|
|
157
|
-
|
158
|
-
|
159
|
-
attr_reader :position
|
160
|
-
|
161
|
-
def evaluate(scopes)
|
162
|
-
u_op(scopes)
|
209
|
+
def evaluate(context = nil)
|
210
|
+
u_op(context)
|
163
211
|
end
|
164
212
|
end
|
165
213
|
|
166
214
|
class BinaryOperation
|
167
215
|
include OperationCommon
|
168
216
|
|
169
|
-
def
|
170
|
-
|
171
|
-
@l_operand = l_operand
|
172
|
-
@r_operand = r_operand
|
173
|
-
@position = position
|
217
|
+
def l_operand
|
218
|
+
operands.first
|
174
219
|
end
|
175
220
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
221
|
+
def r_operand
|
222
|
+
operands.last
|
223
|
+
end
|
224
|
+
|
225
|
+
def evaluate(context = nil)
|
226
|
+
b_op(context)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
class NullCoalescingOperation
|
231
|
+
include OperationCommon
|
232
|
+
|
233
|
+
def l_operand
|
234
|
+
operands.first
|
235
|
+
end
|
236
|
+
|
237
|
+
def r_operand
|
238
|
+
operands.last
|
239
|
+
end
|
180
240
|
|
181
|
-
def evaluate(
|
182
|
-
|
241
|
+
def evaluate(context = nil)
|
242
|
+
null_coalescing_op(context)
|
183
243
|
end
|
184
244
|
end
|
185
245
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
class Pair < Any
|
6
|
+
include Operatable
|
7
|
+
|
8
|
+
uninstantiable_class
|
9
|
+
|
10
|
+
def first
|
11
|
+
@children[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
def second
|
15
|
+
@children[1]
|
16
|
+
end
|
17
|
+
|
18
|
+
def evaluate(_context = nil)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_ruby(context = nil)
|
23
|
+
[first, second].map { _1.to_ruby(context) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_pkl_string(context = nil)
|
27
|
+
to_string(context)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_string(context = nil)
|
31
|
+
element_strings =
|
32
|
+
[first, second].map { _1.to_pkl_string(context) }
|
33
|
+
"Pair(#{element_strings[0]}, #{element_strings[1]})"
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other)
|
37
|
+
other.is_a?(self.class) &&
|
38
|
+
first == other.first && second == other.second
|
39
|
+
end
|
40
|
+
|
41
|
+
define_builtin_property(:first) do
|
42
|
+
first
|
43
|
+
end
|
44
|
+
|
45
|
+
define_builtin_property(:key) do
|
46
|
+
first
|
47
|
+
end
|
48
|
+
|
49
|
+
define_builtin_property(:second) do
|
50
|
+
second
|
51
|
+
end
|
52
|
+
|
53
|
+
define_builtin_property(:value) do
|
54
|
+
second
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -2,45 +2,33 @@
|
|
2
2
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
|
-
class PklModule
|
5
|
+
class PklModule < Any
|
6
6
|
include StructCommon
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
8
|
+
abstract_class
|
9
|
+
klass_name :Module
|
10
|
+
|
11
|
+
def pkl_methods
|
12
|
+
@body&.pkl_methods
|
15
13
|
end
|
16
14
|
|
17
|
-
|
18
|
-
|
15
|
+
def pkl_classes
|
16
|
+
@body&.pkl_classes
|
17
|
+
end
|
19
18
|
|
20
|
-
def evaluate(
|
21
|
-
|
22
|
-
|
23
|
-
end
|
19
|
+
def evaluate(context = nil)
|
20
|
+
resolve_structure(context)
|
21
|
+
super
|
24
22
|
end
|
25
23
|
|
26
|
-
def to_ruby(
|
27
|
-
|
28
|
-
create_pkl_object(s, properties, nil, nil)
|
29
|
-
end
|
24
|
+
def to_ruby(context = nil)
|
25
|
+
to_pkl_object(context)
|
30
26
|
end
|
31
27
|
|
32
28
|
private
|
33
29
|
|
34
|
-
def
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
def evaluate_properties(scopes)
|
39
|
-
properties&.each_with_object([]) do |property, result|
|
40
|
-
property
|
41
|
-
.evaluate(scopes)
|
42
|
-
.then { add_hash_member(result, _1, :name) }
|
43
|
-
end
|
30
|
+
def properties_not_allowed?
|
31
|
+
false
|
44
32
|
end
|
45
33
|
end
|
46
34
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuPkl
|
4
|
+
module Node
|
5
|
+
module ReferenceResolver
|
6
|
+
private
|
7
|
+
|
8
|
+
def resolve_member_reference(context, target, receiver, nullable)
|
9
|
+
scopes, raise_error, ifnone =
|
10
|
+
if receiver
|
11
|
+
evaluate_receiver(receiver, context)&.then do |r|
|
12
|
+
[[r], raise_error?(r, nullable), ifnone_value(r)]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
exec_on(context) do |c|
|
16
|
+
[[c&.objects&.last, Base.instance, *c&.scopes], true]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
find_member(scopes, target, raise_error, ifnone)
|
20
|
+
end
|
21
|
+
|
22
|
+
def raise_error?(receiver, nullable)
|
23
|
+
!(nullable && receiver&.null?)
|
24
|
+
end
|
25
|
+
|
26
|
+
def evaluate_receiver(receiver, context)
|
27
|
+
return unless receiver
|
28
|
+
|
29
|
+
if receiver.structure?
|
30
|
+
receiver
|
31
|
+
.resolve_reference(context)
|
32
|
+
.resolve_structure(context)
|
33
|
+
else
|
34
|
+
receiver.evaluate(context)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_member(scopes, target, raise_error, ifnone)
|
39
|
+
if scope_index.index
|
40
|
+
get_member_node(scopes[scope_index.index], target)
|
41
|
+
else
|
42
|
+
search_member(scopes, target, raise_error, ifnone)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def search_member(scopes, target, raise_error, ifnone)
|
47
|
+
node, index = search_member_from_scopes(scopes, target)
|
48
|
+
if node
|
49
|
+
scope_index.index = index
|
50
|
+
return node
|
51
|
+
end
|
52
|
+
|
53
|
+
raise_error &&
|
54
|
+
(raise unresolve_reference_error(target))
|
55
|
+
|
56
|
+
ifnone
|
57
|
+
end
|
58
|
+
|
59
|
+
def search_member_from_scopes(scopes, target)
|
60
|
+
scopes.reverse_each.with_index do |scope, i|
|
61
|
+
node = get_member_node(scope, target)
|
62
|
+
return [node, scopes.size - i - 1] if node
|
63
|
+
end
|
64
|
+
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
ScopeIndex = Struct.new(:index)
|
69
|
+
|
70
|
+
def scope_index
|
71
|
+
@scope_index ||= ScopeIndex.new
|
72
|
+
end
|
73
|
+
|
74
|
+
def copy_scope_index(target)
|
75
|
+
target.instance_exec(scope_index) { @scope_index = _1 }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|