rupkl 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 |index|
108
- if (0...value.size).include?(index.value)
109
- String.new(nil, value[index.value], nil, position)
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(nil, position)
110
+ Null.new(parent, position)
112
111
  end
113
112
  end
114
113
 
115
- define_builtin_method(:substring, start: Int, exclusive_end: Int) do |s, e|
116
- check_range(s.value, 0)
117
- check_range(e.value, s.value)
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(nil, value[s.value...e.value], nil, position)
122
+ String.new(parent, value[s...e], nil, position)
120
123
  end
121
124
 
122
- define_builtin_method(:substringOrNull, start: Int, exclusive_end: Int) do |s, e|
123
- if inside_range?(s.value, 0) && inside_range?(e.value, s.value)
124
- String.new(nil, value[s.value...e.value], nil, position)
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(nil, position)
133
+ Null.new(parent, position)
127
134
  end
128
135
  end
129
136
 
130
- define_builtin_method(:repeat, count: Int) do |count|
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(nil, result, nil, position)
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 |pattern|
138
- result = value.include?(pattern.value)
139
- Boolean.new(nil, result, position)
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 |pattern|
143
- result = value.start_with?(pattern.value)
144
- Boolean.new(nil, result, position)
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 |pattern|
148
- result = value.end_with?(pattern.value)
149
- Boolean.new(nil, result, position)
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 |pattern|
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 |pattern|
160
- index_of(:index, pattern) do
161
- Null.new(nil, position)
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 |pattern|
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(:lastIndexOfOrNull, pattern: String) do |pattern|
173
- index_of(:rindex, pattern) do
174
- Null.new(nil, position)
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 |n|
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(nil, result, nil, position)
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 |n|
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(nil, result, nil, position)
199
+ String.new(parent, result, nil, position)
191
200
  end
192
201
 
193
- define_builtin_method(:drop, n: Int) do |n|
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(nil, result, nil, position)
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 |n|
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(nil, result, nil, position)
214
+ String.new(parent, result, nil, position)
206
215
  end
207
216
 
208
217
  define_builtin_method(
209
- :replaceFirst,
210
- pattern: String, replacement: String
211
- ) do |pattern, replacement|
212
- result = value.sub(pattern.value, replacement.value)
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
- pattern: String, replacement: String
219
- ) do |pattern, replacement|
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.value))
222
- value.dup.tap { |s| s[index, replacement.value.size] = replacement.value }
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(nil, result, nil, position)
235
+ String.new(parent, result, nil, position)
227
236
  end
228
237
 
229
238
  define_builtin_method(
230
- :replaceAll,
231
- pattern: String, replacement: String
232
- ) do |pattern, replacement|
233
- result = value.gsub(pattern.value, replacement.value)
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
- start: Int, exclusive_end: Int, replacement: String
240
- ) do |start, exclusive_end, replacement|
241
- check_range(start.value, 0)
242
- check_range(exclusive_end.value, start.value)
243
-
244
- range = start.value...exclusive_end.value
245
- result = value.dup.tap { |s| s[range] = replacement.value }
246
- String.new(nil, result, nil, position)
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(nil, value.upcase, nil, position)
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(nil, value.downcase, nil, position)
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(nil, value.reverse, nil, position)
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(nil, value.gsub(pattern, ''), nil, position)
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(nil, value.sub(pattern, ''), nil, position)
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(nil, value.sub(pattern, ''), nil, position)
283
+ String.new(parent, value.sub(pattern, ''), nil, position)
274
284
  end
275
285
 
276
- define_builtin_method(:padStart, width: Int, char: String) do |width, char|
277
- pad(width, char, :pre)
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(:padEnd, width: Int, char: String) do |width, char|
281
- pad(width, char, :post)
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(nil, result, nil, position)
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(nil, result, nil, position)
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(nil, position)
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(nil, position)
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(nil, position)
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 check_range(index, start_index)
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(nil, result, position) || yield
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(nil, result, nil, position)
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(nil, Integer(remove_underscore_from_number(value), 10), position)
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(nil, result, position)
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(nil, result, position)
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
- "'#{self.class.basename}' cannot have a property"
85
+ "'#{class_name}' cannot have a property"
80
86
  elsif entries_not_allowed?
81
- "'#{self.class.basename}' cannot have an entry"
87
+ "'#{class_name}' cannot have an entry"
82
88
  elsif elements_not_allowed?
83
- "'#{self.class.basename}' cannot have an element"
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
- body.properties
96
+ properties.then { _1 && !_1.empty? }
91
97
  end
92
98
 
93
99
  def entries_not_allowed?
94
- body.entries
100
+ entries
95
101
  end
96
102
 
97
103
  def elements_not_allowed?
98
- body.elements
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
- def create_pkl_object(context)
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
- RuPkl::PklObject.new(
132
- to_ruby_hash(@body.properties, c),
133
- to_ruby_hash(@body.entries, c),
134
- to_ruby_array(@body.elements, c)
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 to_ruby_hash(members, context)
140
- members&.to_h { _1.to_ruby(context) }
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 to_ruby_array(members, context)
144
- members&.map { _1.to_ruby(context) }
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 #{self.class.basename} #{to_string_members(context)}"
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