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,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