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
data/lib/rupkl/node/object.rb
CHANGED
@@ -2,64 +2,69 @@
|
|
2
2
|
|
3
3
|
module RuPkl
|
4
4
|
module Node
|
5
|
-
|
6
|
-
|
5
|
+
class ObjectMember
|
6
|
+
include NodeCommon
|
7
7
|
|
8
|
-
def
|
9
|
-
|
8
|
+
def value
|
9
|
+
@value_evaluated || @value
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
evaluate_objects(objects, scopes).to_ruby(nil)
|
17
|
-
end
|
12
|
+
def add_child(child)
|
13
|
+
super
|
14
|
+
assign_evaluaed_value? &&
|
15
|
+
(@value_evaluated = child)
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
|
22
|
-
value.to_pkl_string(scopes)
|
23
|
-
else
|
24
|
-
evaluate_objects(objects, scopes).to_pkl_string(nil)
|
25
|
-
end
|
18
|
+
def visibility
|
19
|
+
@visibility || :lexical
|
26
20
|
end
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
attr_writer :visibility
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def evaluate_value(evaluator, context)
|
27
|
+
@value_evaluated = value.__send__(evaluator, context)
|
28
|
+
value
|
32
29
|
end
|
33
|
-
end
|
34
30
|
|
35
|
-
|
36
|
-
|
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
|
+
end
|
37
39
|
|
38
|
-
|
40
|
+
class ObjectProperty < ObjectMember
|
41
|
+
def initialize(parent, name, value, position)
|
42
|
+
super
|
39
43
|
@name = name
|
40
44
|
@value = value
|
41
|
-
@objects = objects
|
42
|
-
@position = position
|
43
45
|
end
|
44
46
|
|
45
47
|
attr_reader :name
|
46
|
-
attr_reader :value
|
47
|
-
attr_reader :objects
|
48
|
-
attr_reader :position
|
49
48
|
|
50
|
-
def evaluate(
|
51
|
-
|
52
|
-
self
|
49
|
+
def evaluate(context = nil)
|
50
|
+
evaluate_value(__method__, context)
|
51
|
+
self
|
53
52
|
end
|
54
53
|
|
55
|
-
def
|
56
|
-
|
54
|
+
def resolve_structure(context = nil)
|
55
|
+
evaluate_value(__method__, context)
|
56
|
+
self
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
def to_ruby(context = nil)
|
60
|
+
[name.id, evaluate_value(:evaluate, context).to_ruby]
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_pkl_string(context = nil)
|
64
|
+
v = evaluate_value(:evaluate, context).to_pkl_string
|
65
|
+
|
66
|
+
if v.start_with?('new Dynamic')
|
67
|
+
"#{name.id}#{v.delete_prefix('new Dynamic')}"
|
63
68
|
else
|
64
69
|
"#{name.id} = #{v}"
|
65
70
|
end
|
@@ -68,40 +73,52 @@ module RuPkl
|
|
68
73
|
def ==(other)
|
69
74
|
name.id == other.name.id && value == other.value
|
70
75
|
end
|
71
|
-
end
|
72
76
|
|
73
|
-
|
74
|
-
|
77
|
+
def copy(parent = nil)
|
78
|
+
self.class.new(parent, name.copy, copy_value, position)
|
79
|
+
end
|
75
80
|
|
76
|
-
|
81
|
+
private
|
82
|
+
|
83
|
+
def assign_evaluaed_value?
|
84
|
+
@name && @value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class ObjectEntry < ObjectMember
|
89
|
+
def initialize(parent, key, value, position)
|
90
|
+
super
|
77
91
|
@key = key
|
78
92
|
@value = value
|
79
|
-
@objects = objects
|
80
|
-
@position = position
|
81
93
|
end
|
82
94
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
95
|
+
def key
|
96
|
+
@key_evaluated || @key
|
97
|
+
end
|
98
|
+
|
99
|
+
def evaluate(context = nil)
|
100
|
+
evaluate_key(context)
|
101
|
+
evaluate_value(__method__, context)
|
102
|
+
self
|
103
|
+
end
|
87
104
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
self
|
105
|
+
def resolve_structure(context = nil)
|
106
|
+
evaluate_key(context)
|
107
|
+
evaluate_value(__method__, context)
|
108
|
+
self
|
92
109
|
end
|
93
110
|
|
94
|
-
def to_ruby(
|
95
|
-
k =
|
96
|
-
v =
|
111
|
+
def to_ruby(context = nil)
|
112
|
+
k = evaluate_key(context).to_ruby
|
113
|
+
v = evaluate_value(:evaluate, context).to_ruby
|
97
114
|
[k, v]
|
98
115
|
end
|
99
116
|
|
100
|
-
def to_pkl_string(
|
101
|
-
k =
|
102
|
-
v =
|
103
|
-
if v.start_with?('
|
104
|
-
"[#{k}]
|
117
|
+
def to_pkl_string(context = nil)
|
118
|
+
k = evaluate_key(context).to_pkl_string
|
119
|
+
v = evaluate_value(:evaluate, context).to_pkl_string
|
120
|
+
if v.start_with?('new Dynamic')
|
121
|
+
"[#{k}]#{v.delete_prefix('new Dynamic')}"
|
105
122
|
else
|
106
123
|
"[#{k}] = #{v}"
|
107
124
|
end
|
@@ -110,31 +127,310 @@ module RuPkl
|
|
110
127
|
def ==(other)
|
111
128
|
key == other.key && value == other.value
|
112
129
|
end
|
130
|
+
|
131
|
+
def copy(parent = nil)
|
132
|
+
self.class.new(parent, key, copy_value, position)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def evaluate_key(context)
|
138
|
+
@key_evaluated ||=
|
139
|
+
(context || current_context).pop.then do |c|
|
140
|
+
@key.evaluate(c)
|
141
|
+
end
|
142
|
+
@key_evaluated
|
143
|
+
end
|
144
|
+
|
145
|
+
def assign_evaluaed_value?
|
146
|
+
@value && @key && @key_evaluated
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class ObjectElement < ObjectMember
|
151
|
+
def initialize(parent, value, position)
|
152
|
+
super
|
153
|
+
@value = value
|
154
|
+
end
|
155
|
+
|
156
|
+
def evaluate(context = nil)
|
157
|
+
evaluate_value(__method__, context)
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
def resolve_structure(context = nil)
|
162
|
+
evaluate_value(__method__, context)
|
163
|
+
self
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_ruby(context = nil)
|
167
|
+
evaluate_value(:evaluate, context).to_ruby
|
168
|
+
end
|
169
|
+
|
170
|
+
def to_pkl_string(context = nil)
|
171
|
+
evaluate_value(:evaluate, context).to_pkl_string
|
172
|
+
end
|
173
|
+
|
174
|
+
def ==(other)
|
175
|
+
value == other.value
|
176
|
+
end
|
177
|
+
|
178
|
+
def copy(parent = nil)
|
179
|
+
self.class.new(parent, copy_value, position)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def assign_evaluaed_value?
|
185
|
+
@value
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class ObjectBody
|
190
|
+
include NodeCommon
|
191
|
+
include MemberFinder
|
192
|
+
|
193
|
+
def initialize(parent, members, position)
|
194
|
+
super(parent, position)
|
195
|
+
members&.each { add_member(_1) }
|
196
|
+
end
|
197
|
+
|
198
|
+
attr_reader :entries
|
199
|
+
attr_reader :elements
|
200
|
+
attr_reader :pkl_methods
|
201
|
+
attr_reader :pkl_classes
|
202
|
+
|
203
|
+
def properties(visibility: :lexical)
|
204
|
+
if visibility == :lexical
|
205
|
+
@properties
|
206
|
+
&.select { _1.visibility == :lexical || _1.parent.equal?(self) }
|
207
|
+
else
|
208
|
+
@properties
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def fields
|
213
|
+
[*properties, *entries, *elements]
|
214
|
+
end
|
215
|
+
|
216
|
+
def definitions
|
217
|
+
[*pkl_methods, *pkl_classes]
|
218
|
+
end
|
219
|
+
|
220
|
+
def members
|
221
|
+
[*fields, *definitions]
|
222
|
+
end
|
223
|
+
|
224
|
+
def evaluate(context = nil)
|
225
|
+
do_evaluation(__method__, context)
|
226
|
+
end
|
227
|
+
|
228
|
+
def resolve_structure(context = nil)
|
229
|
+
do_evaluation(__method__, context)
|
230
|
+
end
|
231
|
+
|
232
|
+
def copy(parent = nil)
|
233
|
+
copied_members = members.map(&:copy)
|
234
|
+
self.class.new(parent, copied_members, position)
|
235
|
+
end
|
236
|
+
|
237
|
+
def current_context
|
238
|
+
super&.push_scope(self)
|
239
|
+
end
|
240
|
+
|
241
|
+
def merge!(*others)
|
242
|
+
others.each { do_merge(_1) }
|
243
|
+
self
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
def add_member(member)
|
249
|
+
add_child(member)
|
250
|
+
|
251
|
+
varialbe_name = member_variable_name(member)
|
252
|
+
unless instance_variable_defined?(varialbe_name)
|
253
|
+
instance_variable_set(varialbe_name, [])
|
254
|
+
end
|
255
|
+
instance_variable_get(varialbe_name) << member
|
256
|
+
end
|
257
|
+
|
258
|
+
def member_variable_name(member)
|
259
|
+
{
|
260
|
+
ObjectProperty => :@properties,
|
261
|
+
ObjectEntry => :@entries,
|
262
|
+
ObjectElement => :@elements,
|
263
|
+
MethodDefinition => :@pkl_methods
|
264
|
+
}[member.class]
|
265
|
+
end
|
266
|
+
|
267
|
+
def do_evaluation(evaluator, context)
|
268
|
+
(context&.push_scope(self) || current_context).then do |c|
|
269
|
+
fields.each { |f| f.__send__(evaluator, c) }
|
270
|
+
check_duplication
|
271
|
+
self
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def check_duplication
|
276
|
+
check_duplication_members(@properties, :name)
|
277
|
+
check_duplication_members(@entries, :key)
|
278
|
+
check_duplication_members(@pkl_methods, :name)
|
279
|
+
end
|
280
|
+
|
281
|
+
def check_duplication_members(members, accessor)
|
282
|
+
members&.each do |member|
|
283
|
+
duplicate_member?(members, member, accessor) &&
|
284
|
+
(raise EvaluationError.new('duplicate definition of member', member.position))
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def duplicate_member?(members, member, accessor)
|
289
|
+
count =
|
290
|
+
members
|
291
|
+
.count { _1.__send__(accessor) == member.__send__(accessor) }
|
292
|
+
count > 1
|
293
|
+
end
|
294
|
+
|
295
|
+
def do_merge(rhs)
|
296
|
+
rhs_entries, rhs_amend = split_entries(rhs.entries)
|
297
|
+
@properties = merge_hash_members(@properties, rhs.properties, :name)
|
298
|
+
@entries = merge_hash_members(@entries, rhs_entries, :key)
|
299
|
+
@elements = merge_array_members(@elements, rhs.elements, rhs_amend, :key)
|
300
|
+
end
|
301
|
+
|
302
|
+
def split_entries(entries)
|
303
|
+
return [nil, nil] unless entries
|
304
|
+
|
305
|
+
elements_size = elements&.size || 0
|
306
|
+
grouped_entries =
|
307
|
+
entries
|
308
|
+
.group_by { index_node?(_1.key, elements_size) }
|
309
|
+
[grouped_entries[false], grouped_entries[true]]
|
310
|
+
end
|
311
|
+
|
312
|
+
def index_node?(node, elements_size)
|
313
|
+
node.instance_of?(Node::Int) && node.value < elements_size
|
314
|
+
end
|
315
|
+
|
316
|
+
def merge_hash_members(lhs, rhs, accessor)
|
317
|
+
return nil unless lhs || rhs
|
318
|
+
return rhs unless lhs
|
319
|
+
|
320
|
+
rhs&.each do |r|
|
321
|
+
if (index = find_member_index(lhs, r, accessor))
|
322
|
+
lhs[index] = merge_hash_value(lhs[index], r)
|
323
|
+
else
|
324
|
+
r.visibility = :object
|
325
|
+
lhs << r
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
lhs
|
330
|
+
end
|
331
|
+
|
332
|
+
def merge_hash_value(lhs, rhs)
|
333
|
+
if [lhs.value, rhs.value].all? { _1.respond_to?(:body) }
|
334
|
+
lhs.value.merge!(rhs.value)
|
335
|
+
lhs
|
336
|
+
else
|
337
|
+
rhs
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def find_member_index(lhs, rhs, accessor)
|
342
|
+
lhs.find_index { _1.__send__(accessor) == rhs.__send__(accessor) }
|
343
|
+
end
|
344
|
+
|
345
|
+
def merge_array_members(lhs_array, rhs_array, rhs_hash, accessor)
|
346
|
+
return nil unless lhs_array || rhs_array
|
347
|
+
return rhs_array unless lhs_array
|
348
|
+
|
349
|
+
rhs_hash&.each do |r|
|
350
|
+
index = r.__send__(accessor).value
|
351
|
+
lhs_array[index] = merge_array_value(lhs_array[index], r)
|
352
|
+
end
|
353
|
+
|
354
|
+
concat_array_members(lhs_array, rhs_array)
|
355
|
+
end
|
356
|
+
|
357
|
+
def concat_array_members(lhs_array, rhs_array)
|
358
|
+
rhs_array
|
359
|
+
&.each { _1.visibility = :object }
|
360
|
+
&.then { lhs_array.concat(_1) }
|
361
|
+
lhs_array
|
362
|
+
end
|
363
|
+
|
364
|
+
def merge_array_value(lhs, rhs)
|
365
|
+
if [lhs.value, rhs.value].all? { _1.respond_to?(:body) }
|
366
|
+
lhs.value.merge!(rhs.value.body)
|
367
|
+
lhs
|
368
|
+
else
|
369
|
+
lhs.class.new(self, rhs.value, rhs.position)
|
370
|
+
end
|
371
|
+
end
|
113
372
|
end
|
114
373
|
|
115
374
|
class UnresolvedObject
|
116
|
-
|
117
|
-
|
118
|
-
|
375
|
+
include NodeCommon
|
376
|
+
|
377
|
+
def initialize(parent, type, bodies, position)
|
378
|
+
super(parent, type, *bodies, position)
|
379
|
+
@type = type
|
380
|
+
@bodies = bodies
|
119
381
|
end
|
120
382
|
|
121
|
-
attr_reader :
|
122
|
-
attr_reader :
|
383
|
+
attr_reader :type
|
384
|
+
attr_reader :bodies
|
123
385
|
|
124
|
-
def evaluate(
|
125
|
-
|
386
|
+
def evaluate(context = nil)
|
387
|
+
resolve_structure(context).evaluate(context)
|
126
388
|
end
|
127
389
|
|
128
|
-
def
|
129
|
-
|
390
|
+
def resolve_structure(context = nil)
|
391
|
+
exec_on(context) do |c|
|
392
|
+
klass = find_class(c)
|
393
|
+
create_object(klass, c)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def structure?
|
398
|
+
true
|
399
|
+
end
|
400
|
+
|
401
|
+
def copy(parent = nil)
|
402
|
+
self.class.new(parent, type, bodies, position)
|
403
|
+
end
|
404
|
+
|
405
|
+
private
|
406
|
+
|
407
|
+
def find_class(context)
|
408
|
+
type
|
409
|
+
&.find_class(context)
|
410
|
+
&.tap { |klass| check_class(klass) } || Dynamic
|
130
411
|
end
|
131
412
|
|
132
|
-
def
|
133
|
-
|
413
|
+
def check_class(klass)
|
414
|
+
message =
|
415
|
+
if klass.abstract?
|
416
|
+
"cannot instantiate abstract class '#{klass.class_name}'"
|
417
|
+
elsif !klass.instantiable?
|
418
|
+
"cannot instantiate class '#{klass.class_name}'"
|
419
|
+
else
|
420
|
+
return
|
421
|
+
end
|
422
|
+
raise EvaluationError.new(message, position)
|
134
423
|
end
|
135
424
|
|
136
|
-
def
|
137
|
-
|
425
|
+
def create_object(klass, context)
|
426
|
+
klass
|
427
|
+
.new(parent, bodies.first.copy, position)
|
428
|
+
.tap { _1.resolve_structure(context) }
|
429
|
+
.tap do |o|
|
430
|
+
bodies[1..]
|
431
|
+
.map { _1.copy(o).resolve_structure(context) }
|
432
|
+
.then { o.merge!(*_1) }
|
433
|
+
end
|
138
434
|
end
|
139
435
|
end
|
140
436
|
end
|