rupkl 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rupkl/node/amend_expression.rb +2 -2
- data/lib/rupkl/node/any.rb +15 -4
- data/lib/rupkl/node/base.rb +32 -2
- data/lib/rupkl/node/boolean.rb +26 -9
- data/lib/rupkl/node/collection.rb +176 -0
- data/lib/rupkl/node/data_size.rb +254 -0
- data/lib/rupkl/node/duration.rb +266 -0
- data/lib/rupkl/node/dynamic.rb +19 -15
- data/lib/rupkl/node/identifier.rb +5 -1
- data/lib/rupkl/node/if_expression.rb +45 -0
- data/lib/rupkl/node/intseq.rb +84 -0
- data/lib/rupkl/node/listing.rb +11 -4
- data/lib/rupkl/node/map.rb +120 -0
- data/lib/rupkl/node/mapping.rb +13 -6
- data/lib/rupkl/node/member_finder.rb +4 -10
- data/lib/rupkl/node/member_reference.rb +5 -3
- data/lib/rupkl/node/method_call.rb +2 -3
- data/lib/rupkl/node/method_definition.rb +74 -18
- data/lib/rupkl/node/node_common.rb +1 -1
- data/lib/rupkl/node/null.rb +1 -4
- data/lib/rupkl/node/number.rb +133 -45
- data/lib/rupkl/node/object.rb +322 -66
- data/lib/rupkl/node/operation.rb +123 -100
- data/lib/rupkl/node/pair.rb +58 -0
- data/lib/rupkl/node/pkl_module.rb +4 -4
- data/lib/rupkl/node/regex.rb +196 -0
- data/lib/rupkl/node/string.rb +155 -133
- data/lib/rupkl/node/struct_common.rb +70 -35
- data/lib/rupkl/node/value_common.rb +1 -5
- data/lib/rupkl/parser/expression.rb +43 -6
- data/lib/rupkl/parser/misc.rb +20 -0
- data/lib/rupkl/parser/object.rb +96 -13
- data/lib/rupkl/parser/pkl_class.rb +12 -5
- data/lib/rupkl/pkl_object.rb +2 -18
- data/lib/rupkl/version.rb +1 -1
- data/lib/rupkl.rb +10 -2
- metadata +17 -9
@@ -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?)
|
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?)
|
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
|
-
|
49
|
-
|
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 =
|
62
|
-
return if n_args
|
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
|
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
|
-
|
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
|
139
|
-
|
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
|
data/lib/rupkl/node/null.rb
CHANGED
@@ -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
|
data/lib/rupkl/node/number.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
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
|
-
|
13
|
-
|
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
|
17
|
-
|
18
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
147
|
+
self.class.new(parent, result, position)
|
99
148
|
end
|
100
149
|
|
101
|
-
define_builtin_method(
|
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
|
104
|
-
(f
|
105
|
-
Boolean.new(
|
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 |
|
129
|
-
result = value << n.value
|
130
|
-
self.class.new(
|
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 |
|
134
|
-
result = value >> n.value
|
135
|
-
self.class.new(
|
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 |
|
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(
|
234
|
+
self.class.new(parent, result, position)
|
147
235
|
end
|
148
236
|
|
149
|
-
define_builtin_method(:and, n: Int) do |
|
150
|
-
self.class.new(
|
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 |
|
154
|
-
self.class.new(
|
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 |
|
158
|
-
self.class.new(
|
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
|
|