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.
@@ -4,7 +4,7 @@ module RuPkl
4
4
  module Node
5
5
  module MemberFinder
6
6
  def property(name)
7
- value = find_property(name)
7
+ value = find_property(name)&.value
8
8
  return value if value
9
9
 
10
10
  super if self.class <= Any
@@ -22,17 +22,13 @@ module RuPkl
22
22
  def find_property(name)
23
23
  return unless respond_to?(:properties)
24
24
 
25
- properties
26
- &.find { _1.name == name }
27
- &.value
25
+ properties&.find { _1.name == name }
28
26
  end
29
27
 
30
28
  def find_entry(key)
31
29
  return unless respond_to?(:entries)
32
30
 
33
- entries
34
- &.find { _1.key == key }
35
- &.value
31
+ entries&.find { _1.key == key }
36
32
  end
37
33
 
38
34
  def find_element(index)
@@ -40,9 +36,7 @@ module RuPkl
40
36
  return unless elements
41
37
  return unless index.value.is_a?(::Integer)
42
38
 
43
- elements
44
- .find.with_index { |_, i| i == index.value }
45
- &.value
39
+ elements.find.with_index { |_, i| i == index.value }
46
40
  end
47
41
 
48
42
  def find_pkl_method(name)
@@ -22,17 +22,19 @@ module RuPkl
22
22
 
23
23
  def evaluate(context = nil)
24
24
  do_evaluate do
25
- resolve_member_reference(context, member, receiver, nullable?).evaluate
25
+ result = resolve_member_reference(context, member, receiver, nullable?)
26
+ result.evaluate
26
27
  end
27
28
  end
28
29
 
29
30
  def resolve_reference(context = nil)
30
31
  do_evaluate do
31
- resolve_member_reference(context, member, receiver, nullable?).resolve_reference
32
+ result = resolve_member_reference(context, member, receiver, nullable?)
33
+ result.resolve_reference
32
34
  end
33
35
  end
34
36
 
35
- def copy(parent = nil)
37
+ def copy(parent = nil, position = @position)
36
38
  self
37
39
  .class.new(parent, receiver&.copy, member&.copy, nullable?, position)
38
40
  .tap { copy_scope_index(_1) }
@@ -30,7 +30,7 @@ module RuPkl
30
30
  end
31
31
  end
32
32
 
33
- def copy(parent = nil)
33
+ def copy(parent = nil, position = @position)
34
34
  copied_args = arguments&.map(&:copy)
35
35
  self.class
36
36
  .new(parent, receiver&.copy, method_name, copied_args, nullable?, position)
@@ -56,8 +56,7 @@ module RuPkl
56
56
 
57
57
  def execute_method(pkl_method, receiver, context)
58
58
  pkl_method
59
- .call(receiver, arguments, context, position)
60
- .tap { parent&.add_child(_1) }
59
+ .call(receiver, arguments, context, parent, position)
61
60
  end
62
61
  end
63
62
  end
@@ -17,6 +17,20 @@ module RuPkl
17
17
  def check_type(value, context, position)
18
18
  type&.check_type(value, context, position)
19
19
  end
20
+
21
+ def varparam?
22
+ false
23
+ end
24
+ end
25
+
26
+ class VariadicMethodParam < MethodParam
27
+ def check_type(values, context, position)
28
+ values.each { |v| super(v, context, position) }
29
+ end
30
+
31
+ def varparam?
32
+ true
33
+ end
20
34
  end
21
35
 
22
36
  class MethodDefinition
@@ -35,9 +49,13 @@ module RuPkl
35
49
  attr_reader :type
36
50
  attr_reader :body
37
51
 
38
- def call(receiver, arguments, context, position)
52
+ def call(receiver, arguments, context, parent, position)
39
53
  args = evaluate_arguments(arguments, context, position)
40
- execute_method(receiver, args)
54
+ execute_method(receiver, args, parent, position)
55
+ end
56
+
57
+ def coexistable?(other)
58
+ name != other.name
41
59
  end
42
60
 
43
61
  private
@@ -45,29 +63,46 @@ module RuPkl
45
63
  def evaluate_arguments(arguments, context, position)
46
64
  check_arity(arguments, position)
47
65
 
48
- arguments&.zip(params)&.map do |arg, param|
49
- evaluate_argument(arg, param, context)
66
+ params&.each_with_index&.to_h do |param, i|
67
+ arg =
68
+ if param.varparam?
69
+ Array(arguments&.[](i..))
70
+ else
71
+ arguments&.[](i)
72
+ end
73
+ evaluate_argument(param, arg, context)
50
74
  end
51
75
  end
52
76
 
53
- def evaluate_argument(arg, param, context)
54
- value = arg.evaluate(context)
55
- param.check_type(value, context, position)
56
- [param.name, value]
57
- end
58
-
59
77
  def check_arity(arguments, position)
60
78
  n_args = arguments&.size || 0
61
- n_params = params&.size || 0
62
- return if n_args == n_params
79
+ n_params = n_params_range
80
+ return if n_args in ^n_params
63
81
 
64
82
  m = "expected #{n_params} method arguments but got #{n_args}"
65
83
  raise EvaluationError.new(m, position)
66
84
  end
67
85
 
68
- def execute_method(receiver, arguments)
86
+ def n_params_range
87
+ n_params = params&.size || 0
88
+ params&.last&.varparam? && (n_params - 1..) || n_params
89
+ end
90
+
91
+ def evaluate_argument(param, arg, context)
92
+ value =
93
+ if param.varparam?
94
+ arg.map { _1.evaluate(context) }
95
+ else
96
+ arg.evaluate(context)
97
+ end
98
+ param.check_type(value, context, position)
99
+ [param.name, value]
100
+ end
101
+
102
+ def execute_method(receiver, arguments, parent, position)
69
103
  context = create_call_context(receiver, arguments)
70
104
  execute_body(context)
105
+ .copy(parent, position) # set parent and position given from the caller
71
106
  end
72
107
 
73
108
  def create_call_context(receiver, arguments)
@@ -94,7 +129,7 @@ module RuPkl
94
129
  def initialize(arguments)
95
130
  @properties =
96
131
  arguments&.map do |(name, value)|
97
- ObjectProperty.new(nil, name, value, nil)
132
+ ObjectProperty.new(nil, name, value, nil, nil)
98
133
  end
99
134
  super(nil, *@properties, nil)
100
135
  end
@@ -125,18 +160,39 @@ module RuPkl
125
160
  end
126
161
  end
127
162
 
163
+ class BuiltinVariadicMethodParam < VariadicMethodParam
164
+ def initialize(name, klass)
165
+ id = Identifier.new(nil, name, nil)
166
+ type = BuiltinMethodTypeChecker.new(klass)
167
+ super(nil, id, type, nil)
168
+ end
169
+ end
170
+
128
171
  class BuiltinMethodDefinition < MethodDefinition
129
172
  def initialize(name, **params, &body)
130
- param_list = params.map { |n, t| BuiltinMethodParams.new(n, t) }
131
173
  id = Identifier.new(nil, name, nil)
132
- super(nil, id, param_list, nil, nil, nil)
174
+ list = param_list(params)
175
+ super(nil, id, list, nil, nil, nil)
133
176
  @body = body
134
177
  end
135
178
 
179
+ def execute_method(receiver, arguments, parent, position)
180
+ args = arguments&.transform_keys(&:to_sym)
181
+ receiver
182
+ .instance_exec(args, parent, position, &body)
183
+ end
184
+
136
185
  private
137
186
 
138
- def execute_method(receiver, arguments)
139
- receiver.instance_exec(*arguments&.map(&:last), &body)
187
+ def param_list(params)
188
+ params.map do |name, type|
189
+ case type
190
+ in [klass, { varparams: true }]
191
+ BuiltinVariadicMethodParam.new(name, klass)
192
+ else
193
+ BuiltinMethodParams.new(name, type)
194
+ end
195
+ end
140
196
  end
141
197
  end
142
198
  end
@@ -43,7 +43,7 @@ module RuPkl
43
43
  (@children ||= []) << child
44
44
  end
45
45
 
46
- def copy(parent = nil)
46
+ def copy(parent = nil, position = @position)
47
47
  copied_children = children&.map(&:copy)
48
48
  self.class.new(parent, *copied_children, position)
49
49
  end
@@ -4,6 +4,7 @@ module RuPkl
4
4
  module Node
5
5
  class Null < Any
6
6
  include ValueCommon
7
+ include Operatable
7
8
 
8
9
  uninstantiable_class
9
10
 
@@ -15,10 +16,6 @@ module RuPkl
15
16
  'null'
16
17
  end
17
18
 
18
- def undefined_operator?(operator)
19
- [:==, :'!='].none?(operator)
20
- end
21
-
22
19
  def null?
23
20
  true
24
21
  end
@@ -4,31 +4,56 @@ module RuPkl
4
4
  module Node
5
5
  class Number < Any
6
6
  include ValueCommon
7
+ include Operatable
7
8
 
8
- def undefined_operator?(operator)
9
- [:[], :!, :'&&', :'||'].include?(operator)
9
+ abstract_class
10
+ uninstantiable_class
11
+
12
+ def u_op_minus(position)
13
+ self.class.new(nil, -value, position)
10
14
  end
11
15
 
12
- def invalid_r_operand?(operand)
13
- !operand.is_a?(Number)
16
+ {
17
+ b_op_exp: [:**, false], b_op_div: [:/, false],
18
+ b_op_truncating_div: [:/, true], b_op_rem: [:%, false],
19
+ b_op_add: [:+, false], b_op_sub: [:-, false]
20
+ }.each do |method_name, (op, result_int)|
21
+ class_eval(<<~M, __FILE__, __LINE__ + 1)
22
+ # def b_op_exp(r_operand, position)
23
+ # b_op_arithmetic(:'**', r_operand, false, position)
24
+ # end
25
+ def #{method_name}(r_operand, position)
26
+ b_op_arithmetic(:'#{op}', r_operand, #{result_int}, position)
27
+ end
28
+ M
14
29
  end
15
30
 
16
- def coerce(operator, r_operand)
17
- if force_float?(operator, r_operand)
18
- [value.to_f, r_operand.value.to_f]
19
- else
20
- [value.to_i, r_operand.value.to_i]
31
+ def b_op_mul(r_operand, position)
32
+ case r_operand
33
+ when Number then b_op_arithmetic(:*, r_operand, false, position)
34
+ else r_operand.b_op_mul(self, position)
21
35
  end
22
36
  end
23
37
 
24
- def force_float?(operator, r_operand)
25
- operator == :/ ||
26
- operator != :'~/' && [self, r_operand].any?(Float)
38
+ {
39
+ b_op_lt: :<, b_op_gt: :>,
40
+ b_op_le: :<=, b_op_ge: :>=,
41
+ b_op_eq: :==, b_op_ne: :'!='
42
+ }.each do |method_name, op|
43
+ class_eval(<<~M, __FILE__, __LINE__ + 1)
44
+ # def b_op_lt(r_operand, position)
45
+ # l, r = coerce(:'<', r_operand)
46
+ # result = l < r
47
+ # Boolean.new(nil, result, position)
48
+ # end
49
+ def #{method_name}(r_operand, position)
50
+ l, r = coerce(:'#{op}', r_operand)
51
+ result = l #{op} r
52
+ Boolean.new(nil, result, position)
53
+ end
54
+ M
27
55
  end
28
56
 
29
- abstract_class
30
- uninstantiable_class
31
-
32
57
  define_builtin_property(:sign) do
33
58
  result =
34
59
  case value
@@ -39,6 +64,30 @@ module RuPkl
39
64
  self.class.new(self, result, position)
40
65
  end
41
66
 
67
+ [
68
+ :b, :kb, :kib, :mb, :mib, :gb, :gib, :tb, :tib, :pb, :pib
69
+ ].each do |unit|
70
+ class_eval(<<~P, __FILE__, __LINE__ + 1)
71
+ # define_builtin_property(:b) do
72
+ # DataSize.new(self, self, :b, position)
73
+ # end
74
+ define_builtin_property(:#{unit}) do
75
+ DataSize.new(self, self, :#{unit}, position)
76
+ end
77
+ P
78
+ end
79
+
80
+ [:ns, :us, :ms, :s, :min, :h, :d].each do |unit|
81
+ class_eval(<<~P, __FILE__, __LINE__ + 1)
82
+ # define_builtin_property(:ns) do
83
+ # Duration.new(self, self, :ns, position)
84
+ # end
85
+ define_builtin_property(:#{unit}) do
86
+ Duration.new(self, self, :#{unit}, position)
87
+ end
88
+ P
89
+ end
90
+
42
91
  define_builtin_property(:abs) do
43
92
  self.class.new(self, value.abs, position)
44
93
  end
@@ -76,33 +125,72 @@ module RuPkl
76
125
  Boolean.new(self, !value.zero?, position)
77
126
  end
78
127
 
79
- define_builtin_method(:toString) do
80
- String.new(nil, value.to_s, nil, position)
128
+ define_builtin_method(:toString) do |_, parent, position|
129
+ String.new(parent, value.to_s, nil, position)
81
130
  end
82
131
 
83
- define_builtin_method(:toInt) do
84
- Int.new(nil, value.to_i, position)
132
+ define_builtin_method(:toInt) do |_, parent, position|
133
+ Int.new(parent, value.to_i, position)
85
134
  end
86
135
 
87
- define_builtin_method(:toFloat) do
88
- Float.new(nil, value.to_f, position)
136
+ define_builtin_method(:toFloat) do |_, parent, position|
137
+ Float.new(parent, value.to_f, position)
89
138
  end
90
139
 
91
- define_builtin_method(:round) do
140
+ define_builtin_method(:round) do |_, parent, position|
92
141
  result = value.finite? && value.round || value
93
- self.class.new(nil, result, position)
142
+ self.class.new(parent, result, position)
94
143
  end
95
144
 
96
- define_builtin_method(:truncate) do
145
+ define_builtin_method(:truncate) do |_, parent, position|
97
146
  result = value.finite? && value.truncate || value
98
- self.class.new(nil, result, position)
147
+ self.class.new(parent, result, position)
99
148
  end
100
149
 
101
- define_builtin_method(:isBetween, first: Number, last: Number) do |f, l|
150
+ define_builtin_method(
151
+ :isBetween, first: Number, last: Number
152
+ ) do |args, parent, position|
153
+ f = args[:first].value
154
+ l = args[:last].value
102
155
  result =
103
- [f.value, l.value, value].all? { _1.finite? || _1.infinite? } &&
104
- (f.value..l.value).include?(value)
105
- Boolean.new(nil, result, position)
156
+ [f, l, value].all? { _1.finite? || _1.infinite? } &&
157
+ (f..l).include?(value)
158
+ Boolean.new(parent, result, position)
159
+ end
160
+
161
+ private
162
+
163
+ def defined_operator?(operator)
164
+ [:[], :'!@', :'&&', :'||'].none?(operator)
165
+ end
166
+
167
+ def valid_r_operand?(operator, operand)
168
+ case operator
169
+ when :* then operand in Number | DataSize | Duration
170
+ else operand in Number
171
+ end
172
+ end
173
+
174
+ def coerce(operator, r_operand)
175
+ if force_float?(operator, r_operand)
176
+ [value.to_f, r_operand.value.to_f]
177
+ else
178
+ [value.to_i, r_operand.value.to_i]
179
+ end
180
+ end
181
+
182
+ def force_float?(operator, r_operand)
183
+ operator == :/ || [self, r_operand].any?(Float)
184
+ end
185
+
186
+ def b_op_arithmetic(operator, r_operand, result_int, position)
187
+ l, r = coerce(operator, r_operand)
188
+ result = l.__send__(operator, r)
189
+ if result_int || result.integer?
190
+ Int.new(nil, result, position)
191
+ else
192
+ Float.new(nil, result, position)
193
+ end
106
194
  end
107
195
  end
108
196
 
@@ -125,37 +213,37 @@ module RuPkl
125
213
  self.class.new(self, ~value, position)
126
214
  end
127
215
 
128
- define_builtin_method(:shl, n: Int) do |n|
129
- result = value << n.value
130
- self.class.new(self, result, position)
216
+ define_builtin_method(:shl, n: Int) do |args, parent, position|
217
+ result = value << args[:n].value
218
+ self.class.new(parent, result, position)
131
219
  end
132
220
 
133
- define_builtin_method(:shr, n: Int) do |n|
134
- result = value >> n.value
135
- self.class.new(self, result, position)
221
+ define_builtin_method(:shr, n: Int) do |args, parent, position|
222
+ result = value >> args[:n].value
223
+ self.class.new(parent, result, position)
136
224
  end
137
225
 
138
- define_builtin_method(:ushr, n: Int) do |n|
226
+ define_builtin_method(:ushr, n: Int) do |args, parent, position|
139
227
  result =
140
228
  if value.negative?
141
229
  mask = (1 << 63) - 1
142
- n.value.times.inject(value) { |v, _| (v >> 1) & mask }
230
+ args[:n].value.times.inject(value) { |v, _| (v >> 1) & mask }
143
231
  else
144
- value >> n.value
232
+ value >> args[:n].value
145
233
  end
146
- self.class.new(self, result, position)
234
+ self.class.new(parent, result, position)
147
235
  end
148
236
 
149
- define_builtin_method(:and, n: Int) do |n|
150
- self.class.new(nil, value & n.value, position)
237
+ define_builtin_method(:and, n: Int) do |args, parent, position|
238
+ self.class.new(parent, value & args[:n].value, position)
151
239
  end
152
240
 
153
- define_builtin_method(:or, n: Int) do |n|
154
- self.class.new(nil, value | n.value, position)
241
+ define_builtin_method(:or, n: Int) do |args, parent, position|
242
+ self.class.new(parent, value | args[:n].value, position)
155
243
  end
156
244
 
157
- define_builtin_method(:xor, n: Int) do |n|
158
- self.class.new(nil, value ^ n.value, position)
245
+ define_builtin_method(:xor, n: Int) do |args, parent, position|
246
+ self.class.new(parent, value ^ args[:n].value, position)
159
247
  end
160
248
  end
161
249