rupkl 0.1.0 → 0.2.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/rupkl/node/amend_expression.rb +48 -0
  4. data/lib/rupkl/node/any.rb +99 -0
  5. data/lib/rupkl/node/base.rb +45 -0
  6. data/lib/rupkl/node/boolean.rb +12 -4
  7. data/lib/rupkl/node/context.rb +27 -0
  8. data/lib/rupkl/node/declared_type.rb +32 -0
  9. data/lib/rupkl/node/dynamic.rb +28 -59
  10. data/lib/rupkl/node/identifier.rb +16 -6
  11. data/lib/rupkl/node/listing.rb +61 -0
  12. data/lib/rupkl/node/mapping.rb +47 -0
  13. data/lib/rupkl/node/member_finder.rb +55 -0
  14. data/lib/rupkl/node/member_reference.rb +44 -21
  15. data/lib/rupkl/node/method_call.rb +64 -0
  16. data/lib/rupkl/node/method_definition.rb +143 -0
  17. data/lib/rupkl/node/node_common.rb +76 -0
  18. data/lib/rupkl/node/null.rb +27 -0
  19. data/lib/rupkl/node/number.rb +136 -6
  20. data/lib/rupkl/node/object.rb +369 -73
  21. data/lib/rupkl/node/operation.rb +97 -60
  22. data/lib/rupkl/node/pkl_module.rb +16 -28
  23. data/lib/rupkl/node/reference_resolver.rb +79 -0
  24. data/lib/rupkl/node/string.rb +388 -18
  25. data/lib/rupkl/node/struct_common.rb +119 -57
  26. data/lib/rupkl/node/this.rb +17 -0
  27. data/lib/rupkl/node/type_common.rb +34 -0
  28. data/lib/rupkl/node/value_common.rb +18 -9
  29. data/lib/rupkl/parser/expression.rb +158 -41
  30. data/lib/rupkl/parser/identifier.rb +2 -2
  31. data/lib/rupkl/parser/literal.rb +18 -12
  32. data/lib/rupkl/parser/method.rb +41 -0
  33. data/lib/rupkl/parser/misc.rb +4 -0
  34. data/lib/rupkl/parser/object.rb +57 -25
  35. data/lib/rupkl/parser/pkl_class.rb +28 -8
  36. data/lib/rupkl/parser/pkl_module.rb +5 -3
  37. data/lib/rupkl/parser/type.rb +28 -0
  38. data/lib/rupkl/parser.rb +8 -0
  39. data/lib/rupkl/pkl_object.rb +26 -6
  40. data/lib/rupkl/version.rb +1 -1
  41. data/lib/rupkl.rb +25 -4
  42. metadata +33 -3
  43. data/lib/rupkl/node/pkl_class.rb +0 -30
@@ -3,36 +3,50 @@
3
3
  module RuPkl
4
4
  module Node
5
5
  module OperationCommon
6
- def to_ruby(scopes)
7
- evaluate(scopes).to_ruby(nil)
8
- end
6
+ include NodeCommon
9
7
 
10
- def to_string(scopes)
11
- evaluate(scopes).to_string(nil)
8
+ def initialize(parent, operator, *operands, position)
9
+ super(parent, *operands, position)
10
+ @operator = operator
11
+ @operands = operands
12
12
  end
13
13
 
14
- def to_pkl_string(scopes)
15
- evaluate(scopes).to_pkl_string(nil)
14
+ attr_reader :operator
15
+ attr_reader :operands
16
+
17
+ def copy(parent = nil)
18
+ copied_operands = operands.map(&:copy)
19
+ self.class.new(parent, operator, *copied_operands, position)
16
20
  end
17
21
 
18
22
  private
19
23
 
20
- def s_op(scopes)
21
- r = receiver.evaluate(scopes)
24
+ def s_op(context)
25
+ r = receiver.evaluate(context)
22
26
  check_operator(r)
23
27
 
24
- k = key.evaluate(scopes)
28
+ k = key.evaluate(context)
25
29
  check_key_operand(r, k)
26
30
 
27
- r.find_by_key(k) ||
31
+ (v = r.find_by_key(k)) ||
28
32
  begin
29
- message = "cannot find key '#{k.to_pkl_string(scopes)}'"
33
+ message = "cannot find key '#{k.to_pkl_string(context)}'"
30
34
  raise EvaluationError.new(message, position)
31
35
  end
36
+
37
+ v.evaluate
32
38
  end
33
39
 
34
- def u_op(scopes)
35
- o = operand.evaluate(scopes)
40
+ def non_null_op(context)
41
+ o = operand.evaluate(context)
42
+ return o unless o.null?
43
+
44
+ m = "expected a non-null value but got '#{o.to_pkl_string(context)}'"
45
+ raise EvaluationError.new(m, position)
46
+ end
47
+
48
+ def u_op(context)
49
+ o = operand.evaluate(context)
36
50
  check_operator(o)
37
51
 
38
52
  result =
@@ -44,18 +58,26 @@ module RuPkl
44
58
  create_op_result(result)
45
59
  end
46
60
 
47
- def b_op(scopes)
48
- l = l_operand.evaluate(scopes)
61
+ def b_op(context)
62
+ l = l_operand.evaluate(context)
49
63
  check_operator(l)
50
64
  return l if short_circuit?(l)
51
65
 
52
- r = r_operand.evaluate(scopes)
66
+ r = r_operand.evaluate(context)
53
67
  check_r_operand(l, r)
68
+ .then { return _1 if _1 }
54
69
 
55
70
  l, r = l.coerce(operator, r)
56
71
  create_op_result(l.__send__(ruby_op, r))
57
72
  end
58
73
 
74
+ def null_coalescing_op(context)
75
+ l = l_operand.evaluate(context)
76
+ return l unless l.null?
77
+
78
+ r_operand.evaluate(context)
79
+ end
80
+
59
81
  def check_operator(operand)
60
82
  undefined_operator?(operand) &&
61
83
  begin
@@ -87,13 +109,16 @@ module RuPkl
87
109
  end
88
110
 
89
111
  def check_r_operand(l_operand, r_operand)
90
- invalid_r_operand?(l_operand, r_operand) &&
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
112
+ return unless invalid_r_operand?(l_operand, r_operand)
113
+
114
+ if [:==, :'!='].include?(operator)
115
+ create_op_result(operator != :==)
116
+ else
117
+ message =
118
+ "invalid operand type #{r_operand.class.basename} is given " \
119
+ "for operator '#{operator}'"
120
+ raise EvaluationError.new(message, position)
121
+ end
97
122
  end
98
123
 
99
124
  def invalid_r_operand?(l_operand, r_operand)
@@ -115,10 +140,10 @@ module RuPkl
115
140
 
116
141
  def create_op_result(result)
117
142
  case result
118
- when ::Integer then Integer.new(result, position)
119
- when ::Float then Float.new(result, position)
120
- when ::String then String.new(result, nil, position)
121
- when ::TrueClass, ::FalseClass then Boolean.new(result, position)
143
+ when ::Integer then Int.new(parent, result, position)
144
+ when ::Float then Float.new(parent, result, position)
145
+ when ::String then String.new(parent, result, nil, position)
146
+ when true, false then Boolean.new(parent, result, position)
122
147
  end
123
148
  end
124
149
  end
@@ -126,60 +151,72 @@ module RuPkl
126
151
  class SubscriptOperation
127
152
  include OperationCommon
128
153
 
129
- def initialize(receiver, key, position)
130
- @receiver = receiver
131
- @key = key
132
- @position = position
154
+ def receiver
155
+ operands.first
156
+ end
157
+
158
+ def key
159
+ operands.last
133
160
  end
134
161
 
135
- attr_reader :receiver
136
- attr_reader :key
137
- attr_reader :position
162
+ def evaluate(context = nil)
163
+ s_op(context)
164
+ end
165
+ end
166
+
167
+ class NonNullOperation
168
+ include OperationCommon
138
169
 
139
- def operator
140
- :[]
170
+ def operand
171
+ operands.first
141
172
  end
142
173
 
143
- def evaluate(scopes)
144
- s_op(scopes)
174
+ def evaluate(context = nil)
175
+ non_null_op(context)
145
176
  end
146
177
  end
147
178
 
148
179
  class UnaryOperation
149
180
  include OperationCommon
150
181
 
151
- def initialize(operator, operand, position)
152
- @operator = operator
153
- @operand = operand
154
- @position = position
182
+ def operand
183
+ operands.first
155
184
  end
156
185
 
157
- attr_reader :operator
158
- attr_reader :operand
159
- attr_reader :position
160
-
161
- def evaluate(scopes)
162
- u_op(scopes)
186
+ def evaluate(context = nil)
187
+ u_op(context)
163
188
  end
164
189
  end
165
190
 
166
191
  class BinaryOperation
167
192
  include OperationCommon
168
193
 
169
- def initialize(operator, l_operand, r_operand, position)
170
- @operator = operator
171
- @l_operand = l_operand
172
- @r_operand = r_operand
173
- @position = position
194
+ def l_operand
195
+ operands.first
174
196
  end
175
197
 
176
- attr_reader :operator
177
- attr_reader :l_operand
178
- attr_reader :r_operand
179
- attr_reader :position
198
+ def r_operand
199
+ operands.last
200
+ end
201
+
202
+ def evaluate(context = nil)
203
+ b_op(context)
204
+ end
205
+ end
206
+
207
+ class NullCoalescingOperation
208
+ include OperationCommon
209
+
210
+ def l_operand
211
+ operands.first
212
+ end
213
+
214
+ def r_operand
215
+ operands.last
216
+ end
180
217
 
181
- def evaluate(scopes)
182
- b_op(scopes)
218
+ def evaluate(context = nil)
219
+ null_coalescing_op(context)
183
220
  end
184
221
  end
185
222
  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
- def initialize(items, position)
9
- @position = position
10
- items&.each do |item|
11
- case item
12
- when PklClassProperty then add_property(item)
13
- end
14
- end
8
+ abstract_class
9
+ klass_name :Module
10
+
11
+ def properties
12
+ @body&.properties(visibility: :object)
15
13
  end
16
14
 
17
- attr_reader :properties
18
- attr_reader :position
15
+ def pkl_methods
16
+ @body&.pkl_methods
17
+ end
19
18
 
20
- def evaluate(scopes)
21
- push_scope(scopes) do |s|
22
- self.class.new(evaluate_properties(s), position)
23
- end
19
+ def pkl_classes
20
+ @body&.pkl_classes
24
21
  end
25
22
 
26
- def to_ruby(scopes)
27
- push_scope(scopes) do |s|
28
- create_pkl_object(s, properties, nil, nil)
29
- end
23
+ def evaluate(context = nil)
24
+ resolve_structure(context)
25
+ super
30
26
  end
31
27
 
32
28
  private
33
29
 
34
- def add_property(property)
35
- (@properties ||= []) << property
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