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/string.rb
CHANGED
@@ -4,6 +4,7 @@ module RuPkl
|
|
4
4
|
module Node
|
5
5
|
class String < Any
|
6
6
|
include ValueCommon
|
7
|
+
include Operatable
|
7
8
|
|
8
9
|
uninstantiable_class
|
9
10
|
|
@@ -31,7 +32,7 @@ module RuPkl
|
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
|
-
def copy(parent = nil)
|
35
|
+
def copy(parent = nil, position = @position)
|
35
36
|
copied_portions =
|
36
37
|
portions&.map do |portion|
|
37
38
|
portion.is_a?(NodeCommon) && portion.copy || portion
|
@@ -39,14 +40,6 @@ module RuPkl
|
|
39
40
|
self.class.new(parent, nil, copied_portions, position)
|
40
41
|
end
|
41
42
|
|
42
|
-
def undefined_operator?(operator)
|
43
|
-
[:[], :==, :'!=', :+].none?(operator)
|
44
|
-
end
|
45
|
-
|
46
|
-
def invalid_key_operand?(key)
|
47
|
-
!key.is_a?(Int)
|
48
|
-
end
|
49
|
-
|
50
43
|
def find_by_key(key)
|
51
44
|
index = key.value
|
52
45
|
return nil unless (0...value.length).include?(index)
|
@@ -54,6 +47,11 @@ module RuPkl
|
|
54
47
|
self.class.new(parent, value[index], nil, position)
|
55
48
|
end
|
56
49
|
|
50
|
+
def b_op_add(r_operand, position)
|
51
|
+
result = value + r_operand.value
|
52
|
+
String.new(nil, result, nil, position)
|
53
|
+
end
|
54
|
+
|
57
55
|
define_builtin_property(:length) do
|
58
56
|
Int.new(self, value.length, position)
|
59
57
|
end
|
@@ -104,231 +102,247 @@ module RuPkl
|
|
104
102
|
raise EvaluationError.new(message, position)
|
105
103
|
end
|
106
104
|
|
107
|
-
define_builtin_method(:getOrNull, index: Int) do |
|
108
|
-
|
109
|
-
|
105
|
+
define_builtin_method(:getOrNull, index: Int) do |args, parent, position|
|
106
|
+
index = args[:index].value
|
107
|
+
if (0...value.size).include?(index)
|
108
|
+
String.new(parent, value[index], nil, position)
|
110
109
|
else
|
111
|
-
Null.new(
|
110
|
+
Null.new(parent, position)
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
115
|
-
define_builtin_method(
|
116
|
-
|
117
|
-
|
114
|
+
define_builtin_method(
|
115
|
+
:substring, start: Int, exclusive_end: Int
|
116
|
+
) do |args, parent, position|
|
117
|
+
s = args[:start].value
|
118
|
+
e = args[:exclusive_end].value
|
119
|
+
check_range(s, 0, position)
|
120
|
+
check_range(e, s, position)
|
118
121
|
|
119
|
-
String.new(
|
122
|
+
String.new(parent, value[s...e], nil, position)
|
120
123
|
end
|
121
124
|
|
122
|
-
define_builtin_method(
|
123
|
-
|
124
|
-
|
125
|
+
define_builtin_method(
|
126
|
+
:substringOrNull, start: Int, exclusive_end: Int
|
127
|
+
) do |args, parent, position|
|
128
|
+
s = args[:start].value
|
129
|
+
e = args[:exclusive_end].value
|
130
|
+
if inside_range?(s, 0) && inside_range?(e, s)
|
131
|
+
String.new(parent, value[s...e], nil, position)
|
125
132
|
else
|
126
|
-
Null.new(
|
133
|
+
Null.new(parent, position)
|
127
134
|
end
|
128
135
|
end
|
129
136
|
|
130
|
-
define_builtin_method(:repeat, count: Int) do |
|
131
|
-
check_positive_number(count)
|
137
|
+
define_builtin_method(:repeat, count: Int) do |args, parent, position|
|
138
|
+
check_positive_number(args[:count], position)
|
132
139
|
|
133
|
-
result = value * count.value
|
134
|
-
String.new(
|
140
|
+
result = value * args[:count].value
|
141
|
+
String.new(parent, result, nil, position)
|
135
142
|
end
|
136
143
|
|
137
|
-
define_builtin_method(:contains, pattern: String) do |
|
138
|
-
result = value.include?(pattern.value)
|
139
|
-
Boolean.new(
|
144
|
+
define_builtin_method(:contains, pattern: String) do |args, parent, position|
|
145
|
+
result = value.include?(args[:pattern].value)
|
146
|
+
Boolean.new(parent, result, position)
|
140
147
|
end
|
141
148
|
|
142
|
-
define_builtin_method(:startsWith, pattern: String) do |
|
143
|
-
result = value.start_with?(pattern.value)
|
144
|
-
Boolean.new(
|
149
|
+
define_builtin_method(:startsWith, pattern: String) do |args, parent, position|
|
150
|
+
result = value.start_with?(args[:pattern].value)
|
151
|
+
Boolean.new(parent, result, position)
|
145
152
|
end
|
146
153
|
|
147
|
-
define_builtin_method(:endsWith, pattern: String) do |
|
148
|
-
result = value.end_with?(pattern.value)
|
149
|
-
Boolean.new(
|
154
|
+
define_builtin_method(:endsWith, pattern: String) do |args, parent, position|
|
155
|
+
result = value.end_with?(args[:pattern].value)
|
156
|
+
Boolean.new(parent, result, position)
|
150
157
|
end
|
151
158
|
|
152
|
-
define_builtin_method(:indexOf, pattern: String) do |
|
153
|
-
index_of(:index, pattern) do
|
154
|
-
message = "\"#{pattern.value}\" does not occur in \"#{value}\""
|
159
|
+
define_builtin_method(:indexOf, pattern: String) do |args, parent, position|
|
160
|
+
index_of(:index, args[:pattern], parent, position) do
|
161
|
+
message = "\"#{args[:pattern].value}\" does not occur in \"#{value}\""
|
155
162
|
raise EvaluationError.new(message, position)
|
156
163
|
end
|
157
164
|
end
|
158
165
|
|
159
|
-
define_builtin_method(:indexOfOrNull, pattern: String) do |
|
160
|
-
index_of(:index, pattern) do
|
161
|
-
Null.new(
|
166
|
+
define_builtin_method(:indexOfOrNull, pattern: String) do |args, parent, position|
|
167
|
+
index_of(:index, args[:pattern], parent, position) do
|
168
|
+
Null.new(parent, position)
|
162
169
|
end
|
163
170
|
end
|
164
171
|
|
165
|
-
define_builtin_method(:lastIndexOf, pattern: String) do |
|
166
|
-
index_of(:rindex, pattern) do
|
167
|
-
message = "\"#{pattern.value}\" does not occur in \"#{value}\""
|
172
|
+
define_builtin_method(:lastIndexOf, pattern: String) do |args, parent, position|
|
173
|
+
index_of(:rindex, args[:pattern], parent, position) do
|
174
|
+
message = "\"#{args[:pattern].value}\" does not occur in \"#{value}\""
|
168
175
|
raise EvaluationError.new(message, position)
|
169
176
|
end
|
170
177
|
end
|
171
178
|
|
172
|
-
define_builtin_method(
|
173
|
-
|
174
|
-
|
179
|
+
define_builtin_method(
|
180
|
+
:lastIndexOfOrNull, pattern: String
|
181
|
+
) do |args, parent, position|
|
182
|
+
index_of(:rindex, args[:pattern], parent, position) do
|
183
|
+
Null.new(parent, position)
|
175
184
|
end
|
176
185
|
end
|
177
186
|
|
178
|
-
define_builtin_method(:take, n: Int) do |
|
179
|
-
check_positive_number(n)
|
187
|
+
define_builtin_method(:take, n: Int) do |args, parent, position|
|
188
|
+
check_positive_number(args[:n], position)
|
180
189
|
|
181
|
-
result = value[0, n.value] || value
|
182
|
-
String.new(
|
190
|
+
result = value[0, args[:n].value] || value
|
191
|
+
String.new(parent, result, nil, position)
|
183
192
|
end
|
184
193
|
|
185
|
-
define_builtin_method(:takeLast, n: Int) do |
|
186
|
-
check_positive_number(n)
|
194
|
+
define_builtin_method(:takeLast, n: Int) do |args, parent, position|
|
195
|
+
check_positive_number(args[:n], position)
|
187
196
|
|
188
|
-
pos = value.size - n.value
|
197
|
+
pos = value.size - args[:n].value
|
189
198
|
result = pos.negative? && value || value[pos..]
|
190
|
-
String.new(
|
199
|
+
String.new(parent, result, nil, position)
|
191
200
|
end
|
192
201
|
|
193
|
-
define_builtin_method(:drop, n: Int) do |
|
194
|
-
check_positive_number(n)
|
202
|
+
define_builtin_method(:drop, n: Int) do |args, parent, position|
|
203
|
+
check_positive_number(args[:n], position)
|
195
204
|
|
196
|
-
result = value[n.value..] || ''
|
197
|
-
String.new(
|
205
|
+
result = value[args[:n].value..] || ''
|
206
|
+
String.new(parent, result, nil, position)
|
198
207
|
end
|
199
208
|
|
200
|
-
define_builtin_method(:dropLast, n: Int) do |
|
201
|
-
check_positive_number(n)
|
209
|
+
define_builtin_method(:dropLast, n: Int) do |args, parent, position|
|
210
|
+
check_positive_number(args[:n], position)
|
202
211
|
|
203
|
-
length = value.size - n.value
|
212
|
+
length = value.size - args[:n].value
|
204
213
|
result = length.negative? && '' || value[0, length]
|
205
|
-
String.new(
|
214
|
+
String.new(parent, result, nil, position)
|
206
215
|
end
|
207
216
|
|
208
217
|
define_builtin_method(
|
209
|
-
:replaceFirst,
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
String.new(nil, result, nil, position)
|
218
|
+
:replaceFirst, pattern: String, replacement: String
|
219
|
+
) do |args, parent, position|
|
220
|
+
result = value.sub(args[:pattern].value, args[:replacement].value)
|
221
|
+
String.new(parent, result, nil, position)
|
214
222
|
end
|
215
223
|
|
216
224
|
define_builtin_method(
|
217
|
-
:replaceLast,
|
218
|
-
|
219
|
-
|
225
|
+
:replaceLast, pattern: String, replacement: String
|
226
|
+
) do |args, parent, position|
|
227
|
+
pattern = args[:pattern].value
|
228
|
+
replacement = args[:replacement].value
|
220
229
|
result =
|
221
|
-
if (index = value.rindex(pattern
|
222
|
-
value.dup.tap { |s| s[index, replacement.
|
230
|
+
if (index = value.rindex(pattern))
|
231
|
+
value.dup.tap { |s| s[index, replacement.size] = replacement }
|
223
232
|
else
|
224
233
|
value
|
225
234
|
end
|
226
|
-
String.new(
|
235
|
+
String.new(parent, result, nil, position)
|
227
236
|
end
|
228
237
|
|
229
238
|
define_builtin_method(
|
230
|
-
:replaceAll,
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
String.new(nil, result, nil, position)
|
239
|
+
:replaceAll, pattern: String, replacement: String
|
240
|
+
) do |args, parent, position|
|
241
|
+
result = value.gsub(args[:pattern].value, args[:replacement].value)
|
242
|
+
String.new(parent, result, nil, position)
|
235
243
|
end
|
236
244
|
|
237
245
|
define_builtin_method(
|
238
|
-
:replaceRange,
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
246
|
+
:replaceRange, start: Int, exclusive_end: Int, replacement: String
|
247
|
+
) do |args, parent, position|
|
248
|
+
s = args[:start].value
|
249
|
+
e = args[:exclusive_end].value
|
250
|
+
r = args[:replacement].value
|
251
|
+
|
252
|
+
check_range(s, 0, position)
|
253
|
+
check_range(e, s, position)
|
254
|
+
|
255
|
+
result = value.dup.tap { _1[s...e] = r }
|
256
|
+
String.new(parent, result, nil, position)
|
247
257
|
end
|
248
258
|
|
249
|
-
define_builtin_method(:toUpperCase) do
|
250
|
-
String.new(
|
259
|
+
define_builtin_method(:toUpperCase) do |_, parent, position|
|
260
|
+
String.new(parent, value.upcase, nil, position)
|
251
261
|
end
|
252
262
|
|
253
|
-
define_builtin_method(:toLowerCase) do
|
254
|
-
String.new(
|
263
|
+
define_builtin_method(:toLowerCase) do |_, parent, position|
|
264
|
+
String.new(parent, value.downcase, nil, position)
|
255
265
|
end
|
256
266
|
|
257
|
-
define_builtin_method(:reverse) do
|
258
|
-
String.new(
|
267
|
+
define_builtin_method(:reverse) do |_, parent, position|
|
268
|
+
String.new(parent, value.reverse, nil, position)
|
259
269
|
end
|
260
270
|
|
261
|
-
define_builtin_method(:trim) do
|
271
|
+
define_builtin_method(:trim) do |_, parent, position|
|
262
272
|
pattern = /(?:\A\p{White_Space}+)|(?:\p{White_Space}+\z)/
|
263
|
-
String.new(
|
273
|
+
String.new(parent, value.gsub(pattern, ''), nil, position)
|
264
274
|
end
|
265
275
|
|
266
|
-
define_builtin_method(:trimStart) do
|
276
|
+
define_builtin_method(:trimStart) do |_, parent, position|
|
267
277
|
pattern = /\A\p{White_Space}+/
|
268
|
-
String.new(
|
278
|
+
String.new(parent, value.sub(pattern, ''), nil, position)
|
269
279
|
end
|
270
280
|
|
271
|
-
define_builtin_method(:trimEnd) do
|
281
|
+
define_builtin_method(:trimEnd) do |_, parent, position|
|
272
282
|
pattern = /\p{White_Space}+\z/
|
273
|
-
String.new(
|
283
|
+
String.new(parent, value.sub(pattern, ''), nil, position)
|
274
284
|
end
|
275
285
|
|
276
|
-
define_builtin_method(
|
277
|
-
|
286
|
+
define_builtin_method(
|
287
|
+
:padStart, width: Int, char: String
|
288
|
+
) do |args, parent, position|
|
289
|
+
pad(args[:width], args[:char], :pre, parent, position)
|
278
290
|
end
|
279
291
|
|
280
|
-
define_builtin_method(
|
281
|
-
|
292
|
+
define_builtin_method(
|
293
|
+
:padEnd, width: Int, char: String
|
294
|
+
) do |args, parent, position|
|
295
|
+
pad(args[:width], args[:char], :post, parent, position)
|
282
296
|
end
|
283
297
|
|
284
|
-
define_builtin_method(:capitalize) do
|
298
|
+
define_builtin_method(:capitalize) do |_, parent, position|
|
285
299
|
result =
|
286
300
|
value.empty? && value || value.dup.tap { |s| s[0] = s[0].upcase }
|
287
|
-
String.new(
|
301
|
+
String.new(parent, result, nil, position)
|
288
302
|
end
|
289
303
|
|
290
|
-
define_builtin_method(:decapitalize) do
|
304
|
+
define_builtin_method(:decapitalize) do |_, parent, position|
|
291
305
|
result =
|
292
306
|
value.empty? && value || value.dup.tap { |s| s[0] = s[0].downcase }
|
293
|
-
String.new(
|
307
|
+
String.new(parent, result, nil, position)
|
294
308
|
end
|
295
309
|
|
296
|
-
define_builtin_method(:toInt) do
|
297
|
-
to_int do
|
310
|
+
define_builtin_method(:toInt) do |_, parent, position|
|
311
|
+
to_int(parent, position) do
|
298
312
|
message = "cannot parse string as Int \"#{value}\""
|
299
313
|
raise EvaluationError.new(message, position)
|
300
314
|
end
|
301
315
|
end
|
302
316
|
|
303
|
-
define_builtin_method(:toIntOrNull) do
|
304
|
-
to_int do
|
305
|
-
Null.new(
|
317
|
+
define_builtin_method(:toIntOrNull) do |_, parent, position|
|
318
|
+
to_int(parent, position) do
|
319
|
+
Null.new(parent, position)
|
306
320
|
end
|
307
321
|
end
|
308
322
|
|
309
|
-
define_builtin_method(:toFloat) do
|
310
|
-
to_float do
|
323
|
+
define_builtin_method(:toFloat) do |_, parent, position|
|
324
|
+
to_float(parent, position) do
|
311
325
|
message = "cannot parse string as Float \"#{value}\""
|
312
326
|
raise EvaluationError.new(message, position)
|
313
327
|
end
|
314
328
|
end
|
315
329
|
|
316
|
-
define_builtin_method(:toFloatOrNull) do
|
317
|
-
to_float do
|
318
|
-
Null.new(
|
330
|
+
define_builtin_method(:toFloatOrNull) do |_, parent, position|
|
331
|
+
to_float(parent, position) do
|
332
|
+
Null.new(parent, position)
|
319
333
|
end
|
320
334
|
end
|
321
335
|
|
322
|
-
define_builtin_method(:toBoolean) do
|
323
|
-
to_boolean do
|
336
|
+
define_builtin_method(:toBoolean) do |_, parent, position|
|
337
|
+
to_boolean(parent, position) do
|
324
338
|
message = "cannot parse string as Boolean \"#{value}\""
|
325
339
|
raise EvaluationError.new(message, position)
|
326
340
|
end
|
327
341
|
end
|
328
342
|
|
329
|
-
define_builtin_method(:toBooleanOrNull) do
|
330
|
-
to_boolean do
|
331
|
-
Null.new(
|
343
|
+
define_builtin_method(:toBooleanOrNull) do |_, parent, position|
|
344
|
+
to_boolean(parent, position) do
|
345
|
+
Null.new(parent, position)
|
332
346
|
end
|
333
347
|
end
|
334
348
|
|
@@ -359,7 +373,15 @@ module RuPkl
|
|
359
373
|
string.gsub(/([\t\n\r"\\])/) { replace[_1] }
|
360
374
|
end
|
361
375
|
|
362
|
-
def
|
376
|
+
def valid_key_operand?(key)
|
377
|
+
key.is_a?(Int)
|
378
|
+
end
|
379
|
+
|
380
|
+
def defined_operator?(operator)
|
381
|
+
[:[], :+].any?(operator)
|
382
|
+
end
|
383
|
+
|
384
|
+
def check_range(index, start_index, position)
|
363
385
|
return if inside_range?(index, start_index)
|
364
386
|
|
365
387
|
message = "index #{index} is out of range " \
|
@@ -371,12 +393,12 @@ module RuPkl
|
|
371
393
|
(start_index..value.size).include?(index)
|
372
394
|
end
|
373
395
|
|
374
|
-
def index_of(method, pattern)
|
396
|
+
def index_of(method, pattern, parent, position)
|
375
397
|
result = value.__send__(method, pattern.value)
|
376
|
-
result && Int.new(
|
398
|
+
result && Int.new(parent, result, position) || yield
|
377
399
|
end
|
378
400
|
|
379
|
-
def pad(width, char, pre_post)
|
401
|
+
def pad(width, char, pre_post, parent, position)
|
380
402
|
unless char.value.length == 1
|
381
403
|
message = "expected a char, but got \"#{char.value}\""
|
382
404
|
raise EvaluationError.new(message, position)
|
@@ -385,7 +407,7 @@ module RuPkl
|
|
385
407
|
result =
|
386
408
|
pad_prefix_postfix(width, char, pre_post)
|
387
409
|
.then { |pre, post| [pre, value, post].join }
|
388
|
-
String.new(
|
410
|
+
String.new(parent, result, nil, position)
|
389
411
|
end
|
390
412
|
|
391
413
|
def pad_prefix_postfix(width, char, pre_post)
|
@@ -399,13 +421,13 @@ module RuPkl
|
|
399
421
|
end
|
400
422
|
end
|
401
423
|
|
402
|
-
def to_int
|
403
|
-
Int.new(
|
424
|
+
def to_int(parent, position)
|
425
|
+
Int.new(parent, Integer(remove_underscore_from_number(value), 10), position)
|
404
426
|
rescue ArgumentError
|
405
427
|
yield
|
406
428
|
end
|
407
429
|
|
408
|
-
def to_float
|
430
|
+
def to_float(parent, position)
|
409
431
|
result =
|
410
432
|
case value
|
411
433
|
when 'NaN' then ::Float::NAN
|
@@ -413,7 +435,7 @@ module RuPkl
|
|
413
435
|
when '-Infinity' then -::Float::INFINITY
|
414
436
|
else Float(remove_underscore_from_number(value))
|
415
437
|
end
|
416
|
-
Float.new(
|
438
|
+
Float.new(parent, result, position)
|
417
439
|
rescue ArgumentError
|
418
440
|
yield
|
419
441
|
end
|
@@ -422,14 +444,14 @@ module RuPkl
|
|
422
444
|
string.gsub(/(?:(?<=\d)|(?<=.[eE][+-]))_+/, '')
|
423
445
|
end
|
424
446
|
|
425
|
-
def to_boolean
|
447
|
+
def to_boolean(parent, position)
|
426
448
|
result =
|
427
449
|
case value
|
428
450
|
when /\Atrue\z/i then true
|
429
451
|
when /\Afalse\z/i then false
|
430
452
|
else return yield
|
431
453
|
end
|
432
|
-
Boolean.new(
|
454
|
+
Boolean.new(parent, result, position)
|
433
455
|
end
|
434
456
|
end
|
435
457
|
end
|
@@ -9,11 +9,30 @@ module RuPkl
|
|
9
9
|
def initialize(parent, body, position)
|
10
10
|
super
|
11
11
|
@body = body
|
12
|
-
body && check_members
|
13
12
|
end
|
14
13
|
|
15
14
|
attr_reader :body
|
16
15
|
|
16
|
+
def properties(visibility: :object)
|
17
|
+
@body&.properties(visibility: visibility)
|
18
|
+
end
|
19
|
+
|
20
|
+
def entries
|
21
|
+
@body&.entries
|
22
|
+
end
|
23
|
+
|
24
|
+
def elements
|
25
|
+
@body&.elements
|
26
|
+
end
|
27
|
+
|
28
|
+
def members(visibility: :object)
|
29
|
+
@body&.members(visibility: visibility)
|
30
|
+
end
|
31
|
+
|
32
|
+
def items
|
33
|
+
@body&.items
|
34
|
+
end
|
35
|
+
|
17
36
|
def evaluate(context = nil)
|
18
37
|
do_evaluation(__method__, context, 1) do |c|
|
19
38
|
@body&.evaluate(c)
|
@@ -25,15 +44,10 @@ module RuPkl
|
|
25
44
|
do_evaluation(__method__, context, 1) do |c|
|
26
45
|
@body&.resolve_structure(c)
|
27
46
|
end
|
47
|
+
@body && check_members
|
28
48
|
self
|
29
49
|
end
|
30
50
|
|
31
|
-
def to_ruby(context = nil)
|
32
|
-
do_evaluation(__method__, context, 1, PklObject::SELF) do |c|
|
33
|
-
create_pkl_object(c)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
51
|
def to_pkl_string(context = nil)
|
38
52
|
to_string(context)
|
39
53
|
end
|
@@ -52,50 +66,42 @@ module RuPkl
|
|
52
66
|
true
|
53
67
|
end
|
54
68
|
|
55
|
-
def copy(parent = nil)
|
69
|
+
def copy(parent = nil, position = @position)
|
56
70
|
self.class.new(parent, @body&.copy, position)
|
57
71
|
end
|
58
72
|
|
59
73
|
def merge!(*bodies)
|
60
74
|
return unless @body
|
61
75
|
|
62
|
-
@body.merge!(*bodies)
|
76
|
+
@body.merge!(*bodies.compact)
|
63
77
|
check_members
|
64
78
|
end
|
65
79
|
|
66
|
-
def undefined_operator?(operator)
|
67
|
-
[:[], :==, :'!='].none?(operator)
|
68
|
-
end
|
69
|
-
|
70
|
-
def coerce(_operator, r_operand)
|
71
|
-
[self, r_operand]
|
72
|
-
end
|
73
|
-
|
74
80
|
private
|
75
81
|
|
76
82
|
def check_members
|
77
83
|
message =
|
78
84
|
if properties_not_allowed?
|
79
|
-
"'#{
|
85
|
+
"'#{class_name}' cannot have a property"
|
80
86
|
elsif entries_not_allowed?
|
81
|
-
"'#{
|
87
|
+
"'#{class_name}' cannot have an entry"
|
82
88
|
elsif elements_not_allowed?
|
83
|
-
"'#{
|
89
|
+
"'#{class_name}' cannot have an element"
|
84
90
|
end
|
85
91
|
message &&
|
86
92
|
(raise EvaluationError.new(message, position))
|
87
93
|
end
|
88
94
|
|
89
95
|
def properties_not_allowed?
|
90
|
-
|
96
|
+
properties.then { _1 && !_1.empty? }
|
91
97
|
end
|
92
98
|
|
93
99
|
def entries_not_allowed?
|
94
|
-
|
100
|
+
entries
|
95
101
|
end
|
96
102
|
|
97
103
|
def elements_not_allowed?
|
98
|
-
|
104
|
+
elements
|
99
105
|
end
|
100
106
|
|
101
107
|
def do_evaluation(method, context, limit, ifreachlimit = nil)
|
@@ -126,30 +132,55 @@ module RuPkl
|
|
126
132
|
end
|
127
133
|
end
|
128
134
|
|
129
|
-
|
135
|
+
SELF = Object.new.freeze
|
136
|
+
|
137
|
+
def to_pkl_object(context)
|
138
|
+
to_ruby_object(context) do |properties, entries, elements|
|
139
|
+
PklObject.new do |object|
|
140
|
+
[
|
141
|
+
replace_self_hash(properties, object),
|
142
|
+
replace_self_hash(entries, object),
|
143
|
+
replace_self_array(elements, object)
|
144
|
+
]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_ruby_object(context)
|
150
|
+
do_evaluation(__method__, context, 1, SELF) do |c|
|
151
|
+
results = convert_members(c)
|
152
|
+
yield(*results)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def convert_members(context)
|
130
157
|
context.push_scope(@body).then do |c|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
158
|
+
to_ruby = proc { _1.to_ruby(c) }
|
159
|
+
[
|
160
|
+
properties&.to_h(&to_ruby),
|
161
|
+
entries&.to_h(&to_ruby),
|
162
|
+
elements&.map(&to_ruby)
|
163
|
+
]
|
136
164
|
end
|
137
165
|
end
|
138
166
|
|
139
|
-
def
|
140
|
-
|
167
|
+
def replace_self_hash(hash, replacement)
|
168
|
+
hash&.each do |key, value|
|
169
|
+
hash[key] = replacement if value.equal?(SELF)
|
170
|
+
end
|
141
171
|
end
|
142
172
|
|
143
|
-
def
|
144
|
-
|
173
|
+
def replace_self_array(array, replacement)
|
174
|
+
array&.each_with_index do |value, i|
|
175
|
+
array[i] = replacement if value.equal?(SELF)
|
176
|
+
end
|
145
177
|
end
|
146
178
|
|
147
179
|
def to_string_object(context)
|
148
|
-
"new #{
|
180
|
+
"new #{class_name} #{to_string_members(context)}"
|
149
181
|
end
|
150
182
|
|
151
183
|
def to_string_members(context)
|
152
|
-
members = @body.members
|
153
184
|
return '{}' if members.empty?
|
154
185
|
|
155
186
|
context.push_scope(@body).then do |c|
|
@@ -159,6 +190,10 @@ module RuPkl
|
|
159
190
|
.then { "{ #{_1} }" }
|
160
191
|
end
|
161
192
|
end
|
193
|
+
|
194
|
+
def defined_operator?(operator)
|
195
|
+
operator == :[]
|
196
|
+
end
|
162
197
|
end
|
163
198
|
end
|
164
199
|
end
|