kumi 0.0.6 → 0.0.8

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +34 -177
  3. data/README.md +41 -7
  4. data/docs/SYNTAX.md +2 -7
  5. data/docs/features/array-broadcasting.md +1 -1
  6. data/docs/schema_metadata/broadcasts.md +53 -0
  7. data/docs/schema_metadata/cascades.md +45 -0
  8. data/docs/schema_metadata/declarations.md +54 -0
  9. data/docs/schema_metadata/dependencies.md +57 -0
  10. data/docs/schema_metadata/evaluation_order.md +29 -0
  11. data/docs/schema_metadata/examples.md +95 -0
  12. data/docs/schema_metadata/inferred_types.md +46 -0
  13. data/docs/schema_metadata/inputs.md +86 -0
  14. data/docs/schema_metadata.md +108 -0
  15. data/examples/game_of_life.rb +1 -1
  16. data/examples/static_analysis_errors.rb +7 -7
  17. data/lib/kumi/analyzer.rb +20 -20
  18. data/lib/kumi/compiler.rb +44 -50
  19. data/lib/kumi/core/analyzer/analysis_state.rb +39 -0
  20. data/lib/kumi/core/analyzer/constant_evaluator.rb +59 -0
  21. data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +248 -0
  22. data/lib/kumi/core/analyzer/passes/declaration_validator.rb +45 -0
  23. data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +153 -0
  24. data/lib/kumi/core/analyzer/passes/input_collector.rb +139 -0
  25. data/lib/kumi/core/analyzer/passes/name_indexer.rb +26 -0
  26. data/lib/kumi/core/analyzer/passes/pass_base.rb +52 -0
  27. data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +111 -0
  28. data/lib/kumi/core/analyzer/passes/toposorter.rb +110 -0
  29. data/lib/kumi/core/analyzer/passes/type_checker.rb +162 -0
  30. data/lib/kumi/core/analyzer/passes/type_consistency_checker.rb +48 -0
  31. data/lib/kumi/core/analyzer/passes/type_inferencer.rb +236 -0
  32. data/lib/kumi/core/analyzer/passes/unsat_detector.rb +406 -0
  33. data/lib/kumi/core/analyzer/passes/visitor_pass.rb +44 -0
  34. data/lib/kumi/core/atom_unsat_solver.rb +396 -0
  35. data/lib/kumi/core/compiled_schema.rb +43 -0
  36. data/lib/kumi/core/constraint_relationship_solver.rb +641 -0
  37. data/lib/kumi/core/domain/enum_analyzer.rb +55 -0
  38. data/lib/kumi/core/domain/range_analyzer.rb +85 -0
  39. data/lib/kumi/core/domain/validator.rb +82 -0
  40. data/lib/kumi/core/domain/violation_formatter.rb +42 -0
  41. data/lib/kumi/core/error_reporter.rb +166 -0
  42. data/lib/kumi/core/error_reporting.rb +97 -0
  43. data/lib/kumi/core/errors.rb +120 -0
  44. data/lib/kumi/core/evaluation_wrapper.rb +40 -0
  45. data/lib/kumi/core/explain.rb +295 -0
  46. data/lib/kumi/core/export/deserializer.rb +41 -0
  47. data/lib/kumi/core/export/errors.rb +14 -0
  48. data/lib/kumi/core/export/node_builders.rb +142 -0
  49. data/lib/kumi/core/export/node_registry.rb +54 -0
  50. data/lib/kumi/core/export/node_serializers.rb +158 -0
  51. data/lib/kumi/core/export/serializer.rb +25 -0
  52. data/lib/kumi/core/export.rb +35 -0
  53. data/lib/kumi/core/function_registry/collection_functions.rb +202 -0
  54. data/lib/kumi/core/function_registry/comparison_functions.rb +33 -0
  55. data/lib/kumi/core/function_registry/conditional_functions.rb +38 -0
  56. data/lib/kumi/core/function_registry/function_builder.rb +95 -0
  57. data/lib/kumi/core/function_registry/logical_functions.rb +44 -0
  58. data/lib/kumi/core/function_registry/math_functions.rb +74 -0
  59. data/lib/kumi/core/function_registry/string_functions.rb +57 -0
  60. data/lib/kumi/core/function_registry/type_functions.rb +53 -0
  61. data/lib/kumi/{function_registry.rb → core/function_registry.rb} +28 -36
  62. data/lib/kumi/core/input/type_matcher.rb +97 -0
  63. data/lib/kumi/core/input/validator.rb +51 -0
  64. data/lib/kumi/core/input/violation_creator.rb +52 -0
  65. data/lib/kumi/core/json_schema/generator.rb +65 -0
  66. data/lib/kumi/core/json_schema/validator.rb +27 -0
  67. data/lib/kumi/core/json_schema.rb +16 -0
  68. data/lib/kumi/core/ruby_parser/build_context.rb +27 -0
  69. data/lib/kumi/core/ruby_parser/declaration_reference_proxy.rb +38 -0
  70. data/lib/kumi/core/ruby_parser/dsl.rb +14 -0
  71. data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +138 -0
  72. data/lib/kumi/core/ruby_parser/expression_converter.rb +128 -0
  73. data/lib/kumi/core/ruby_parser/guard_rails.rb +45 -0
  74. data/lib/kumi/core/ruby_parser/input_builder.rb +127 -0
  75. data/lib/kumi/core/ruby_parser/input_field_proxy.rb +48 -0
  76. data/lib/kumi/core/ruby_parser/input_proxy.rb +31 -0
  77. data/lib/kumi/core/ruby_parser/nested_input.rb +17 -0
  78. data/lib/kumi/core/ruby_parser/parser.rb +71 -0
  79. data/lib/kumi/core/ruby_parser/schema_builder.rb +175 -0
  80. data/lib/kumi/core/ruby_parser/sugar.rb +263 -0
  81. data/lib/kumi/core/ruby_parser.rb +12 -0
  82. data/lib/kumi/core/schema_instance.rb +111 -0
  83. data/lib/kumi/core/types/builder.rb +23 -0
  84. data/lib/kumi/core/types/compatibility.rb +96 -0
  85. data/lib/kumi/core/types/formatter.rb +26 -0
  86. data/lib/kumi/core/types/inference.rb +42 -0
  87. data/lib/kumi/core/types/normalizer.rb +72 -0
  88. data/lib/kumi/core/types/validator.rb +37 -0
  89. data/lib/kumi/core/types.rb +66 -0
  90. data/lib/kumi/core/vectorization_metadata.rb +110 -0
  91. data/lib/kumi/errors.rb +1 -112
  92. data/lib/kumi/registry.rb +37 -0
  93. data/lib/kumi/schema.rb +13 -7
  94. data/lib/kumi/schema_metadata.rb +524 -0
  95. data/lib/kumi/syntax/array_expression.rb +6 -6
  96. data/lib/kumi/syntax/call_expression.rb +4 -4
  97. data/lib/kumi/syntax/cascade_expression.rb +4 -4
  98. data/lib/kumi/syntax/case_expression.rb +4 -4
  99. data/lib/kumi/syntax/declaration_reference.rb +4 -4
  100. data/lib/kumi/syntax/hash_expression.rb +4 -4
  101. data/lib/kumi/syntax/input_declaration.rb +5 -5
  102. data/lib/kumi/syntax/input_element_reference.rb +5 -5
  103. data/lib/kumi/syntax/input_reference.rb +5 -5
  104. data/lib/kumi/syntax/literal.rb +4 -4
  105. data/lib/kumi/syntax/node.rb +34 -34
  106. data/lib/kumi/syntax/root.rb +6 -6
  107. data/lib/kumi/syntax/trait_declaration.rb +4 -4
  108. data/lib/kumi/syntax/value_declaration.rb +4 -4
  109. data/lib/kumi/version.rb +1 -1
  110. data/lib/kumi.rb +14 -0
  111. data/migrate_to_core_iterative.rb +938 -0
  112. data/scripts/generate_function_docs.rb +9 -9
  113. metadata +85 -69
  114. data/lib/generators/trait_engine/templates/schema_spec.rb.erb +0 -27
  115. data/lib/kumi/analyzer/analysis_state.rb +0 -37
  116. data/lib/kumi/analyzer/constant_evaluator.rb +0 -57
  117. data/lib/kumi/analyzer/passes/broadcast_detector.rb +0 -251
  118. data/lib/kumi/analyzer/passes/declaration_validator.rb +0 -43
  119. data/lib/kumi/analyzer/passes/dependency_resolver.rb +0 -151
  120. data/lib/kumi/analyzer/passes/input_collector.rb +0 -137
  121. data/lib/kumi/analyzer/passes/name_indexer.rb +0 -24
  122. data/lib/kumi/analyzer/passes/pass_base.rb +0 -50
  123. data/lib/kumi/analyzer/passes/semantic_constraint_validator.rb +0 -110
  124. data/lib/kumi/analyzer/passes/toposorter.rb +0 -108
  125. data/lib/kumi/analyzer/passes/type_checker.rb +0 -162
  126. data/lib/kumi/analyzer/passes/type_consistency_checker.rb +0 -46
  127. data/lib/kumi/analyzer/passes/type_inferencer.rb +0 -232
  128. data/lib/kumi/analyzer/passes/unsat_detector.rb +0 -406
  129. data/lib/kumi/analyzer/passes/visitor_pass.rb +0 -42
  130. data/lib/kumi/atom_unsat_solver.rb +0 -394
  131. data/lib/kumi/compiled_schema.rb +0 -41
  132. data/lib/kumi/constraint_relationship_solver.rb +0 -638
  133. data/lib/kumi/domain/enum_analyzer.rb +0 -53
  134. data/lib/kumi/domain/range_analyzer.rb +0 -83
  135. data/lib/kumi/domain/validator.rb +0 -80
  136. data/lib/kumi/domain/violation_formatter.rb +0 -40
  137. data/lib/kumi/error_reporter.rb +0 -164
  138. data/lib/kumi/error_reporting.rb +0 -95
  139. data/lib/kumi/evaluation_wrapper.rb +0 -38
  140. data/lib/kumi/explain.rb +0 -281
  141. data/lib/kumi/export/deserializer.rb +0 -39
  142. data/lib/kumi/export/errors.rb +0 -12
  143. data/lib/kumi/export/node_builders.rb +0 -140
  144. data/lib/kumi/export/node_registry.rb +0 -52
  145. data/lib/kumi/export/node_serializers.rb +0 -156
  146. data/lib/kumi/export/serializer.rb +0 -23
  147. data/lib/kumi/export.rb +0 -33
  148. data/lib/kumi/function_registry/collection_functions.rb +0 -200
  149. data/lib/kumi/function_registry/comparison_functions.rb +0 -31
  150. data/lib/kumi/function_registry/conditional_functions.rb +0 -36
  151. data/lib/kumi/function_registry/function_builder.rb +0 -93
  152. data/lib/kumi/function_registry/logical_functions.rb +0 -42
  153. data/lib/kumi/function_registry/math_functions.rb +0 -72
  154. data/lib/kumi/function_registry/string_functions.rb +0 -54
  155. data/lib/kumi/function_registry/type_functions.rb +0 -51
  156. data/lib/kumi/input/type_matcher.rb +0 -95
  157. data/lib/kumi/input/validator.rb +0 -49
  158. data/lib/kumi/input/violation_creator.rb +0 -50
  159. data/lib/kumi/parser/build_context.rb +0 -25
  160. data/lib/kumi/parser/declaration_reference_proxy.rb +0 -36
  161. data/lib/kumi/parser/dsl.rb +0 -12
  162. data/lib/kumi/parser/dsl_cascade_builder.rb +0 -136
  163. data/lib/kumi/parser/expression_converter.rb +0 -126
  164. data/lib/kumi/parser/guard_rails.rb +0 -43
  165. data/lib/kumi/parser/input_builder.rb +0 -125
  166. data/lib/kumi/parser/input_field_proxy.rb +0 -46
  167. data/lib/kumi/parser/input_proxy.rb +0 -29
  168. data/lib/kumi/parser/nested_input.rb +0 -15
  169. data/lib/kumi/parser/parser.rb +0 -68
  170. data/lib/kumi/parser/schema_builder.rb +0 -173
  171. data/lib/kumi/parser/sugar.rb +0 -261
  172. data/lib/kumi/schema_instance.rb +0 -109
  173. data/lib/kumi/types/builder.rb +0 -21
  174. data/lib/kumi/types/compatibility.rb +0 -94
  175. data/lib/kumi/types/formatter.rb +0 -24
  176. data/lib/kumi/types/inference.rb +0 -40
  177. data/lib/kumi/types/normalizer.rb +0 -70
  178. data/lib/kumi/types/validator.rb +0 -35
  179. data/lib/kumi/types.rb +0 -64
  180. data/lib/kumi/vectorization_metadata.rb +0 -108
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- module Types
5
- # Builds complex type structures
6
- class Builder
7
- def self.array(elem_type)
8
- raise ArgumentError, "Invalid array element type: #{elem_type}" unless Validator.valid_type?(elem_type)
9
-
10
- { array: elem_type }
11
- end
12
-
13
- def self.hash(key_type, val_type)
14
- raise ArgumentError, "Invalid hash key type: #{key_type}" unless Validator.valid_type?(key_type)
15
- raise ArgumentError, "Invalid hash value type: #{val_type}" unless Validator.valid_type?(val_type)
16
-
17
- { hash: [key_type, val_type] }
18
- end
19
- end
20
- end
21
- end
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- module Types
5
- # Handles type compatibility and unification
6
- class Compatibility
7
- # Check if two types are compatible
8
- def self.compatible?(type1, type2)
9
- # Any type is compatible with anything
10
- return true if type1 == :any || type2 == :any
11
-
12
- # Exact match
13
- return true if type1 == type2
14
-
15
- # Generic array compatibility: :array is compatible with any structured array
16
- return true if (type1 == :array && Validator.array_type?(type2)) ||
17
- (type2 == :array && Validator.array_type?(type1))
18
-
19
- # Numeric compatibility
20
- return true if numeric_compatible?(type1, type2)
21
-
22
- # Array compatibility
23
- return array_compatible?(type1, type2) if array_types?(type1, type2)
24
-
25
- # Hash compatibility
26
- return hash_compatible?(type1, type2) if hash_types?(type1, type2)
27
-
28
- false
29
- end
30
-
31
- # Find the most specific common type between two types
32
- def self.unify(type1, type2)
33
- return type1 if type1 == type2
34
-
35
- # :any unifies to the other type (more specific)
36
- return type2 if type1 == :any
37
- return type1 if type2 == :any
38
-
39
- # Generic array unification: structured array is more specific than :array
40
- return type2 if type1 == :array && Validator.array_type?(type2)
41
- return type1 if type2 == :array && Validator.array_type?(type1)
42
-
43
- # Numeric unification
44
- if numeric_compatible?(type1, type2)
45
- return :integer if type1 == :integer && type2 == :integer
46
-
47
- return :float # One or both are float
48
- end
49
-
50
- # Array unification
51
- if array_types?(type1, type2)
52
- elem1 = type1[:array]
53
- elem2 = type2[:array]
54
- unified_elem = unify(elem1, elem2)
55
- return Kumi::Types.array(unified_elem)
56
- end
57
-
58
- # Hash unification
59
- if hash_types?(type1, type2)
60
- key1, val1 = type1[:hash]
61
- key2, val2 = type2[:hash]
62
- unified_key = unify(key1, key2)
63
- unified_val = unify(val1, val2)
64
- return Kumi::Types.hash(unified_key, unified_val)
65
- end
66
-
67
- # Fall back to :any for incompatible types
68
- :any
69
- end
70
-
71
- def self.numeric_compatible?(type1, type2)
72
- numeric_types = %i[integer float]
73
- numeric_types.include?(type1) && numeric_types.include?(type2)
74
- end
75
-
76
- def self.array_types?(type1, type2)
77
- Validator.array_type?(type1) && Validator.array_type?(type2)
78
- end
79
-
80
- def self.hash_types?(type1, type2)
81
- Validator.hash_type?(type1) && Validator.hash_type?(type2)
82
- end
83
-
84
- def self.array_compatible?(type1, type2)
85
- compatible?(type1[:array], type2[:array])
86
- end
87
-
88
- def self.hash_compatible?(type1, type2)
89
- compatible?(type1[:hash][0], type2[:hash][0]) &&
90
- compatible?(type1[:hash][1], type2[:hash][1])
91
- end
92
- end
93
- end
94
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- module Types
5
- # Formats types for display and debugging
6
- class Formatter
7
- # Convert types to string representation
8
- def self.type_to_s(type)
9
- case type
10
- when Hash
11
- if type[:array]
12
- "array(#{type_to_s(type[:array])})"
13
- elsif type[:hash]
14
- "hash(#{type_to_s(type[:hash][0])}, #{type_to_s(type[:hash][1])})"
15
- else
16
- type.to_s
17
- end
18
- else
19
- type.to_s
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "date"
4
-
5
- module Kumi
6
- module Types
7
- # Infers types from Ruby values
8
- class Inference
9
- def self.infer_from_value(value)
10
- case value
11
- when String then :string
12
- when Integer then :integer
13
- when Float then :float
14
- when TrueClass, FalseClass then :boolean
15
- when Symbol then :symbol
16
- when Regexp then :regexp
17
- when Time then :time
18
- when DateTime then :datetime
19
- when Date then :date
20
- when Array
21
- return Kumi::Types.array(:any) if value.empty?
22
-
23
- # Infer element type from first element (simple heuristic)
24
- first_elem_type = infer_from_value(value.first)
25
- Kumi::Types.array(first_elem_type)
26
- when Hash
27
- return Kumi::Types.hash(:any, :any) if value.empty?
28
-
29
- # Infer key/value types from first pair (simple heuristic)
30
- first_key, first_value = value.first
31
- key_type = infer_from_value(first_key)
32
- value_type = infer_from_value(first_value)
33
- Kumi::Types.hash(key_type, value_type)
34
- else
35
- :any
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "date"
4
-
5
- module Kumi
6
- module Types
7
- # Normalizes different type inputs to canonical forms
8
- class Normalizer
9
- # Type normalization - convert various inputs to canonical type symbols
10
- def self.normalize(type_input)
11
- case type_input
12
- when Symbol
13
- return type_input if Validator.valid_type?(type_input)
14
-
15
- raise ArgumentError, "Invalid type symbol: #{type_input}"
16
- when String
17
- symbol_type = type_input.to_sym
18
- return symbol_type if Validator.valid_type?(symbol_type)
19
-
20
- raise ArgumentError, "Invalid type string: #{type_input}"
21
- when Hash
22
- return type_input if Validator.valid_type?(type_input)
23
-
24
- raise ArgumentError, "Invalid type hash: #{type_input}"
25
- when Class
26
- # Handle Ruby class inputs
27
- case type_input.name
28
- when "Integer" then :integer
29
- when "String" then :string
30
- when "Float" then :float
31
- when "TrueClass", "FalseClass" then :boolean
32
- when "Array" then raise ArgumentError, "Use array(:type) helper for array types"
33
- when "Hash" then raise ArgumentError, "Use hash(:key_type, :value_type) helper for hash types"
34
- else
35
- raise ArgumentError, "Unsupported class type: #{type_input}"
36
- end
37
- else
38
- case type_input
39
- when Integer, Float, Numeric
40
- raise ArgumentError, "Type must be a symbol, got #{type_input} (#{type_input.class})"
41
- else
42
- raise ArgumentError, "Invalid type input: #{type_input} (#{type_input.class})"
43
- end
44
- end
45
- end
46
-
47
- # Legacy compatibility - coerce old constants to symbols
48
- def self.coerce(type_input)
49
- # Handle legacy constant usage
50
- return type_input if type_input.is_a?(Symbol) && Validator.valid_type?(type_input)
51
-
52
- # Handle legacy constant objects
53
- case type_input
54
- when STRING then :string
55
- when INT then :integer
56
- when FLOAT, NUMERIC then :float # Both FLOAT and NUMERIC map to :float
57
- when BOOL then :boolean
58
- when ANY then :any
59
- when SYMBOL then :symbol
60
- when REGEXP then :regexp
61
- when TIME then :time
62
- when DATE then :date
63
- when DATETIME then :datetime
64
- else
65
- normalize(type_input)
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- module Types
5
- # Validates type definitions and structures
6
- class Validator
7
- VALID_TYPES = %i[string integer float boolean any symbol regexp time date datetime array].freeze
8
-
9
- def self.valid_type?(type)
10
- return true if VALID_TYPES.include?(type)
11
- return true if array_type?(type)
12
- return true if hash_type?(type)
13
-
14
- false
15
- end
16
-
17
- def self.array_type?(type)
18
- type.is_a?(Hash) && type.keys == [:array] && valid_type?(type[:array])
19
- end
20
-
21
- def self.hash_type?(type)
22
- type.is_a?(Hash) &&
23
- type.keys.sort == [:hash] &&
24
- type[:hash].is_a?(Array) &&
25
- type[:hash].size == 2 &&
26
- valid_type?(type[:hash][0]) &&
27
- valid_type?(type[:hash][1])
28
- end
29
-
30
- def self.primitive_type?(type)
31
- VALID_TYPES.include?(type)
32
- end
33
- end
34
- end
35
- end
data/lib/kumi/types.rb DELETED
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- module Types
5
- # Re-export constants for compatibility
6
- VALID_TYPES = Validator::VALID_TYPES
7
-
8
- # Validation methods
9
- def self.valid_type?(type)
10
- Validator.valid_type?(type)
11
- end
12
-
13
- # Type builders
14
- def self.array(elem_type)
15
- Builder.array(elem_type)
16
- end
17
-
18
- def self.hash(key_type, val_type)
19
- Builder.hash(key_type, val_type)
20
- end
21
-
22
- # Normalization
23
- def self.normalize(type_input)
24
- Normalizer.normalize(type_input)
25
- end
26
-
27
- def self.coerce(type_input)
28
- Normalizer.coerce(type_input)
29
- end
30
-
31
- # Compatibility and unification
32
- def self.compatible?(type1, type2)
33
- Compatibility.compatible?(type1, type2)
34
- end
35
-
36
- def self.unify(type1, type2)
37
- Compatibility.unify(type1, type2)
38
- end
39
-
40
- # Type inference
41
- def self.infer_from_value(value)
42
- Inference.infer_from_value(value)
43
- end
44
-
45
- # Formatting
46
- def self.type_to_s(type)
47
- Formatter.type_to_s(type)
48
- end
49
-
50
- # Legacy compatibility constants (will be phased out)
51
- # These should be replaced with symbols in user code over time
52
- STRING = :string
53
- INT = :integer # NOTE: using :integer instead of :int for clarity
54
- FLOAT = :float
55
- BOOL = :boolean
56
- ANY = :any
57
- SYMBOL = :symbol
58
- REGEXP = :regexp
59
- TIME = :time
60
- DATE = :date
61
- DATETIME = :datetime
62
- NUMERIC = :float # Legacy: represents numeric compatibility
63
- end
64
- end
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Kumi
4
- # Metadata system for vectorization detection and handling
5
- module VectorizationMetadata
6
- # Tracks which declarations are arrays with children (vectorizable)
7
- class ArrayDeclarationTracker
8
- def initialize
9
- @array_declarations = {}
10
- end
11
-
12
- def register_array(name, children)
13
- @array_declarations[name] = children.map(&:name)
14
- end
15
-
16
- def array_declaration?(name)
17
- @array_declarations.key?(name)
18
- end
19
-
20
- def array_children(name)
21
- @array_declarations[name] || []
22
- end
23
-
24
- def all_arrays
25
- @array_declarations.keys
26
- end
27
- end
28
-
29
- # Detects vectorized operations in expressions
30
- class VectorizationDetector
31
- def initialize(array_tracker)
32
- @array_tracker = array_tracker
33
- end
34
-
35
- # Check if an expression should be vectorized
36
- def vectorized_expression?(expression)
37
- case expression
38
- when Kumi::Syntax::CallExpression
39
- vectorized_call?(expression)
40
- when Kumi::Syntax::InputElementReference
41
- vectorized_element_reference?(expression)
42
- else
43
- false
44
- end
45
- end
46
-
47
- # Check if a function call should be treated as a reducer
48
- def reducer_function?(fn_name, args)
49
- REDUCER_FUNCTIONS.include?(fn_name) &&
50
- args.any? { |arg| vectorized_expression?(arg) }
51
- end
52
-
53
- private
54
-
55
- REDUCER_FUNCTIONS = %i[sum min max size length first last].freeze
56
-
57
- def vectorized_call?(call_expr)
58
- # Arithmetic operations between array elements are vectorized
59
- ARITHMETIC_OPERATIONS.include?(call_expr.fn_name) &&
60
- call_expr.args.any? { |arg| vectorized_expression?(arg) }
61
- end
62
-
63
- def vectorized_element_reference?(elem_ref)
64
- return false unless elem_ref.path.size >= 2
65
-
66
- array_name, _field_name = elem_ref.path
67
- @array_tracker.array_declaration?(array_name)
68
- end
69
-
70
- ARITHMETIC_OPERATIONS = %i[add subtract multiply divide modulo power].freeze
71
- end
72
-
73
- # Metadata about how values should be computed
74
- class ComputationMetadata
75
- attr_reader :vectorized_values, :reducer_values, :scalar_values
76
-
77
- def initialize
78
- @vectorized_values = Set.new
79
- @reducer_values = Set.new
80
- @scalar_values = Set.new
81
- end
82
-
83
- def mark_vectorized(name)
84
- @vectorized_values.add(name)
85
- end
86
-
87
- def mark_reducer(name)
88
- @reducer_values.add(name)
89
- end
90
-
91
- def mark_scalar(name)
92
- @scalar_values.add(name)
93
- end
94
-
95
- def vectorized?(name)
96
- @vectorized_values.include?(name)
97
- end
98
-
99
- def reducer?(name)
100
- @reducer_values.include?(name)
101
- end
102
-
103
- def scalar?(name)
104
- @scalar_values.include?(name)
105
- end
106
- end
107
- end
108
- end