rupkl 0.1.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.
Files changed (51) 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 +110 -0
  5. data/lib/rupkl/node/base.rb +75 -0
  6. data/lib/rupkl/node/boolean.rb +30 -5
  7. data/lib/rupkl/node/collection.rb +176 -0
  8. data/lib/rupkl/node/context.rb +27 -0
  9. data/lib/rupkl/node/data_size.rb +254 -0
  10. data/lib/rupkl/node/declared_type.rb +32 -0
  11. data/lib/rupkl/node/duration.rb +266 -0
  12. data/lib/rupkl/node/dynamic.rb +33 -60
  13. data/lib/rupkl/node/identifier.rb +19 -5
  14. data/lib/rupkl/node/if_expression.rb +45 -0
  15. data/lib/rupkl/node/intseq.rb +84 -0
  16. data/lib/rupkl/node/listing.rb +68 -0
  17. data/lib/rupkl/node/map.rb +120 -0
  18. data/lib/rupkl/node/mapping.rb +54 -0
  19. data/lib/rupkl/node/member_finder.rb +49 -0
  20. data/lib/rupkl/node/member_reference.rb +46 -21
  21. data/lib/rupkl/node/method_call.rb +63 -0
  22. data/lib/rupkl/node/method_definition.rb +199 -0
  23. data/lib/rupkl/node/node_common.rb +76 -0
  24. data/lib/rupkl/node/null.rb +24 -0
  25. data/lib/rupkl/node/number.rb +228 -10
  26. data/lib/rupkl/node/object.rb +626 -74
  27. data/lib/rupkl/node/operation.rb +175 -115
  28. data/lib/rupkl/node/pair.rb +58 -0
  29. data/lib/rupkl/node/pkl_module.rb +16 -28
  30. data/lib/rupkl/node/reference_resolver.rb +79 -0
  31. data/lib/rupkl/node/regex.rb +196 -0
  32. data/lib/rupkl/node/string.rb +415 -23
  33. data/lib/rupkl/node/struct_common.rb +150 -53
  34. data/lib/rupkl/node/this.rb +17 -0
  35. data/lib/rupkl/node/type_common.rb +34 -0
  36. data/lib/rupkl/node/value_common.rb +18 -13
  37. data/lib/rupkl/parser/expression.rb +197 -43
  38. data/lib/rupkl/parser/identifier.rb +2 -2
  39. data/lib/rupkl/parser/literal.rb +18 -12
  40. data/lib/rupkl/parser/method.rb +41 -0
  41. data/lib/rupkl/parser/misc.rb +24 -0
  42. data/lib/rupkl/parser/object.rb +141 -26
  43. data/lib/rupkl/parser/pkl_class.rb +37 -10
  44. data/lib/rupkl/parser/pkl_module.rb +5 -3
  45. data/lib/rupkl/parser/type.rb +28 -0
  46. data/lib/rupkl/parser.rb +8 -0
  47. data/lib/rupkl/pkl_object.rb +11 -7
  48. data/lib/rupkl/version.rb +1 -1
  49. data/lib/rupkl.rb +35 -6
  50. metadata +45 -7
  51. data/lib/rupkl/node/pkl_class.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8b6a7346123ff0c771a201f1218f0c2d92e3c34a16e4fe0f668724eb53726ee
4
- data.tar.gz: 169990d7f909f37f72ea97ba2ff44c9634137fead23791ab6a80fddd9b3af109
3
+ metadata.gz: f84f197edd08a0aa623b11f6fd14c83e3fefaf880f0b70a8f6e84eb6599f4ad6
4
+ data.tar.gz: 9f3294541be5d4ea4ac6c71fe12f501752cf3b6c447194a8b6254723742c169b
5
5
  SHA512:
6
- metadata.gz: 50e6f855bec47026a3a6f4b8b61b9fd61ceafc7686bcd0a51f459a42ae88a97ee954fb362f3450c89d6499fe6e1d97f2b2350350a2820607c007bc7a8e8d8190
7
- data.tar.gz: ad63c41fa79cc9b487d6d3c7f4b129febbf914e564f15d9921072cf4680442dcc77c605d8d7cc283aa15662f15247f427ccbd218c2a1856681ca402500e2810f
6
+ metadata.gz: a4ed0408a38e1db11008cd03922c295ac0e0fd42b22a2d9c6d47bd91e73f3de344aa2af1559d4e83d407a49cc51ec95e595da83ce0572d6b1ab86d17c4f79e05
7
+ data.tar.gz: a055b31ced095d7e8f851830c03daf63388d1ef23f343e7f1dd6292205e9a0a99a54bc2b5119e9489487084fe28b2d3a37af28c21197b0d0f7367e39446bffbb
data/README.md CHANGED
@@ -116,7 +116,7 @@ Pkl code snippets used for RSpec examples are originaly from:
116
116
  ## Copyright & License
117
117
 
118
118
  Copyright © 2024 Taichi Ishitani.
119
- RuPkl is licensed under the terms of the [MIT License](https://opensource.org/licenses/MIT), see [LICENSE](LICENSE) for further details.
119
+ RuPkl is licensed under the terms of the [MIT License](https://opensource.org/licenses/MIT), see [LICENSE.txt](LICENSE.txt) for further details.
120
120
 
121
121
  ## Code of Conduct
122
122
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuPkl
4
+ module Node
5
+ class AmendExpression
6
+ include NodeCommon
7
+
8
+ def initialize(parent, target, bodies, position)
9
+ super(parent, target, *bodies, position)
10
+ @target = target
11
+ @bodies = bodies
12
+ end
13
+
14
+ attr_reader :target
15
+ attr_reader :bodies
16
+
17
+ def evaluate(context = nil)
18
+ resolve_structure(context).evaluate(context)
19
+ end
20
+
21
+ def resolve_structure(context = nil)
22
+ t =
23
+ target
24
+ .resolve_reference(context)
25
+ .resolve_structure(context)
26
+ t.respond_to?(:body) ||
27
+ begin
28
+ message = "cannot amend the target type #{t.class_name}"
29
+ raise EvaluationError.new(message, position)
30
+ end
31
+ do_amend(t.copy(parent))
32
+ end
33
+
34
+ def copy(parent = nil, position = @position)
35
+ self.class.new(parent, target.copy, bodies.each(&:copy), position)
36
+ end
37
+
38
+ private
39
+
40
+ def do_amend(target)
41
+ bodies
42
+ .map { _1.copy(target).resolve_structure }
43
+ .then { target.merge!(*_1) }
44
+ target
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuPkl
4
+ module Node
5
+ class Any
6
+ include NodeCommon
7
+
8
+ class << self
9
+ def abstract?
10
+ @abstract || false
11
+ end
12
+
13
+ def instantiable?
14
+ !@uninstantiable
15
+ end
16
+
17
+ def class_name
18
+ @class_name ||= to_s.split('::').last.to_sym
19
+ end
20
+
21
+ def builtin_property(name)
22
+ @builtin_properties&.[](name.to_sym)
23
+ end
24
+
25
+ def buildin_method(name)
26
+ @builtin_methods&.[](name.to_sym)
27
+ end
28
+
29
+ private
30
+
31
+ def abstract_class
32
+ @abstract = true
33
+ end
34
+
35
+ def uninstantiable_class
36
+ @uninstantiable = true
37
+ end
38
+
39
+ def klass_name(name)
40
+ @class_name = name
41
+ end
42
+
43
+ def define_builtin_property(name, &body)
44
+ (@builtin_properties ||= {})[name] = body
45
+ end
46
+
47
+ def define_builtin_method(name, ...)
48
+ (@builtin_methods ||= {})[name] = BuiltinMethodDefinition.new(name, ...)
49
+ end
50
+ end
51
+
52
+ abstract_class
53
+ uninstantiable_class
54
+
55
+ def property(name)
56
+ builtin_property(name)
57
+ end
58
+
59
+ def pkl_method(name)
60
+ buildin_method(name)
61
+ end
62
+
63
+ def null?
64
+ false
65
+ end
66
+
67
+ def class_name
68
+ self.class.class_name
69
+ end
70
+
71
+ private
72
+
73
+ def builtin_property(name)
74
+ self.class.ancestors.each do |klass|
75
+ next unless klass.respond_to?(:builtin_property)
76
+
77
+ body = klass.builtin_property(name)
78
+ return instance_exec(&body) if body
79
+ end
80
+
81
+ nil
82
+ end
83
+
84
+ def buildin_method(name)
85
+ self.class.ancestors.each do |klass|
86
+ next unless klass.respond_to?(:buildin_method)
87
+
88
+ method = klass.buildin_method(name)
89
+ return method if method
90
+ end
91
+
92
+ nil
93
+ end
94
+
95
+ def check_positive_number(number, position)
96
+ return unless number.value.negative?
97
+
98
+ m = "expected a positive number, but got '#{number.value}'"
99
+ raise EvaluationError.new(m, position)
100
+ end
101
+
102
+ protected
103
+
104
+ def execute_builtin_method(name, arguments, parent, position)
105
+ buildin_method(name)
106
+ .execute_method(self, arguments, parent, position)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuPkl
4
+ module Node
5
+ class Base < PklModule
6
+ include Singleton
7
+
8
+ def initialize
9
+ super(nil, nil, nil)
10
+ end
11
+
12
+ attr_reader :pkl_classes
13
+
14
+ class << self
15
+ private
16
+
17
+ def add_builtin_class(klass)
18
+ instance.instance_eval do
19
+ name = klass.class_name
20
+ (@pkl_classes ||= {})[name] = klass
21
+ end
22
+ end
23
+ end
24
+
25
+ add_builtin_class Any
26
+ add_builtin_class Boolean
27
+ add_builtin_class Number
28
+ add_builtin_class Int
29
+ add_builtin_class Float
30
+ add_builtin_class String
31
+ add_builtin_class Dynamic
32
+ add_builtin_class Mapping
33
+ add_builtin_class Listing
34
+ add_builtin_class PklModule
35
+
36
+ define_builtin_property(:NaN) do
37
+ Float.new(self, ::Float::NAN, position)
38
+ end
39
+
40
+ define_builtin_property(:Infinity) do
41
+ Float.new(self, ::Float::INFINITY, position)
42
+ end
43
+
44
+ define_builtin_method(
45
+ :List, elements: [Any, varparams: true]
46
+ ) do |args, parent, position|
47
+ List.new(parent, args[:elements], position)
48
+ end
49
+
50
+ define_builtin_method(
51
+ :Set, elements: [Any, varparams: true]
52
+ ) do |args, parent, position|
53
+ Set.new(parent, args[:elements], position)
54
+ end
55
+
56
+ define_builtin_method(:Pair, first: Any, second: Any) do |args, parent, position|
57
+ Pair.new(parent, args[:first], args[:second], position)
58
+ end
59
+
60
+ define_builtin_method(
61
+ :Map, entries: [Any, varparams: true]
62
+ ) do |args, parent, position|
63
+ Map.new(parent, args[:entries], position)
64
+ end
65
+
66
+ define_builtin_method(:IntSeq, start: Int, last: Int) do |args, parent, position|
67
+ IntSeq.new(parent, args[:start], args[:last], nil, position)
68
+ end
69
+
70
+ define_builtin_method(:Regex, pattern: String) do |args, parent, position|
71
+ Regex.new(parent, args[:pattern], position)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -2,15 +2,40 @@
2
2
 
3
3
  module RuPkl
4
4
  module Node
5
- class Boolean
5
+ class Boolean < Any
6
6
  include ValueCommon
7
+ include Operatable
7
8
 
8
- def evaluate(_scopes)
9
- self
9
+ uninstantiable_class
10
+
11
+ def u_op_negate(position)
12
+ Boolean.new(nil, !value, position)
13
+ end
14
+
15
+ def b_op_and(r_operand, position)
16
+ result = value && r_operand.value
17
+ Boolean.new(nil, result, position)
18
+ end
19
+
20
+ def b_op_or(r_operand, position)
21
+ result = value || r_operand.value
22
+ Boolean.new(nil, result, position)
10
23
  end
11
24
 
12
- def undefined_operator?(operator)
13
- [:!, :==, :'!=', :'&&', :'||'].none?(operator)
25
+ define_builtin_method(:xor, other: Boolean) do |args, parent, position|
26
+ result = value ^ args[:other].value
27
+ Boolean.new(parent, result, position)
28
+ end
29
+
30
+ define_builtin_method(:implies, other: Boolean) do |args, parent, position|
31
+ result = !value || args[:other].value
32
+ Boolean.new(parent, result, position)
33
+ end
34
+
35
+ private
36
+
37
+ def defined_operator?(operator)
38
+ [:'!@', :'&&', :'||'].any?(operator)
14
39
  end
15
40
 
16
41
  def short_circuit?(operator)
@@ -0,0 +1,176 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuPkl
4
+ module Node
5
+ class Collection < Any
6
+ include Operatable
7
+
8
+ abstract_class
9
+ uninstantiable_class
10
+
11
+ def initialize(parent, elements, position)
12
+ super(parent, *elements, position)
13
+ end
14
+
15
+ alias_method :elements, :children
16
+
17
+ def evaluate(_context = nil)
18
+ self
19
+ end
20
+
21
+ def to_ruby(context = nil)
22
+ elements&.map { _1.to_ruby(context) } || []
23
+ end
24
+
25
+ def to_pkl_string(context = nil)
26
+ to_string(context)
27
+ end
28
+
29
+ def to_string(context = nil)
30
+ element_string =
31
+ elements
32
+ &.map { _1.to_pkl_string(context) }
33
+ &.join(', ')
34
+ "#{class_name}(#{element_string})"
35
+ end
36
+
37
+ def ==(other)
38
+ other.instance_of?(self.class) && elements == other.elements
39
+ end
40
+
41
+ def b_op_add(r_operand, position)
42
+ result =
43
+ if elements && r_operand.elements
44
+ elements + r_operand.elements
45
+ else
46
+ elements || r_operand.elements
47
+ end
48
+ self.class.new(nil, result, position)
49
+ end
50
+
51
+ define_builtin_property(:length) do
52
+ result = elements&.size || 0
53
+ Int.new(self, result, position)
54
+ end
55
+
56
+ define_builtin_property(:isEmpty) do
57
+ result = elements.nil? || elements.empty?
58
+ Boolean.new(self, result, position)
59
+ end
60
+
61
+ define_builtin_property(:first) do
62
+ elements&.first || raise_wrong_collection_size_error
63
+ end
64
+
65
+ define_builtin_property(:firstOrNull) do
66
+ elements&.first || Null.new(parent, position)
67
+ end
68
+
69
+ define_builtin_property(:rest) do
70
+ if (result = elements&.[](1..))
71
+ self.class.new(parent, result, position)
72
+ else
73
+ raise_wrong_collection_size_error
74
+ end
75
+ end
76
+
77
+ define_builtin_property(:restOrNull) do
78
+ if (result = elements&.[](1..))
79
+ self.class.new(parent, result, position)
80
+ else
81
+ Null.new(parent, position)
82
+ end
83
+ end
84
+
85
+ define_builtin_property(:last) do
86
+ elements&.last || raise_wrong_collection_size_error
87
+ end
88
+
89
+ define_builtin_property(:lastOrNull) do
90
+ elements&.last || Null.new(parent, position)
91
+ end
92
+
93
+ define_builtin_property(:single) do
94
+ size = elements&.size || 0
95
+ size == 1 && elements.first ||
96
+ raise_wrong_collection_size_error { 'expected a single-element collection' }
97
+ end
98
+
99
+ define_builtin_property(:singleOrNull) do
100
+ size = elements&.size || 0
101
+ size == 1 && elements.first || Null.new(parent, position)
102
+ end
103
+
104
+ define_builtin_property(:lastIndex) do
105
+ result = (elements&.size || 0) - 1
106
+ Int.new(parent, result, position)
107
+ end
108
+
109
+ private
110
+
111
+ def remove_duplicate_elements(elements)
112
+ elements
113
+ &.each_with_object([]) { |e, a| a.include?(e) || (a << e) }
114
+ end
115
+
116
+ def raise_wrong_collection_size_error
117
+ message =
118
+ if block_given?
119
+ yield
120
+ else
121
+ 'expected a non-empty collection'
122
+ end
123
+ raise EvaluationError.new(message, position)
124
+ end
125
+
126
+ def valid_r_operand?(operator, operand)
127
+ operand.is_a?(self.class) ||
128
+ operator == :+ && (operand in List | Set)
129
+ end
130
+ end
131
+
132
+ class List < Collection
133
+ include MemberFinder
134
+ undef_method :pkl_method
135
+
136
+ uninstantiable_class
137
+
138
+ def find_by_key(key)
139
+ find_element(key)
140
+ end
141
+
142
+ define_builtin_property(:isDistinct) do
143
+ result =
144
+ elements.nil? ||
145
+ elements.all? { |e| elements.one?(e) }
146
+ Boolean.new(parent, result, position)
147
+ end
148
+
149
+ define_builtin_property(:distinct) do
150
+ result = remove_duplicate_elements(elements)
151
+ List.new(parent, result, position)
152
+ end
153
+
154
+ private
155
+
156
+ def defined_operator?(operator)
157
+ [:[], :+].any?(operator)
158
+ end
159
+ end
160
+
161
+ class Set < Collection
162
+ uninstantiable_class
163
+
164
+ def initialize(parent, elements, position)
165
+ unique_elements = remove_duplicate_elements(elements)
166
+ super(parent, unique_elements, position)
167
+ end
168
+
169
+ private
170
+
171
+ def defined_operator?(operator)
172
+ operator == :+
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuPkl
4
+ module Node
5
+ class Context
6
+ def initialize(scopes, objects)
7
+ @scopes = scopes
8
+ @objects = objects
9
+ end
10
+
11
+ attr_reader :scopes
12
+ attr_reader :objects
13
+
14
+ def push_scope(scope)
15
+ Context.new([*scopes, scope], objects)
16
+ end
17
+
18
+ def push_object(object)
19
+ Context.new(scopes, [*objects, object])
20
+ end
21
+
22
+ def pop
23
+ Context.new(scopes&.slice(..-2), objects&.slice(..-2))
24
+ end
25
+ end
26
+ end
27
+ end