kumi 0.0.7 → 0.0.9
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.
- checksums.yaml +4 -4
- data/CLAUDE.md +1 -1
- data/README.md +21 -5
- data/docs/AST.md +7 -0
- data/docs/features/README.md +7 -0
- data/docs/features/s-expression-printer.md +77 -0
- data/examples/game_of_life.rb +1 -1
- data/examples/static_analysis_errors.rb +7 -7
- data/lib/kumi/analyzer.rb +15 -15
- data/lib/kumi/compiler.rb +6 -6
- data/lib/kumi/core/analyzer/analysis_state.rb +39 -0
- data/lib/kumi/core/analyzer/constant_evaluator.rb +59 -0
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +248 -0
- data/lib/kumi/core/analyzer/passes/declaration_validator.rb +45 -0
- data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +153 -0
- data/lib/kumi/core/analyzer/passes/input_collector.rb +139 -0
- data/lib/kumi/core/analyzer/passes/name_indexer.rb +26 -0
- data/lib/kumi/core/analyzer/passes/pass_base.rb +52 -0
- data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +111 -0
- data/lib/kumi/core/analyzer/passes/toposorter.rb +110 -0
- data/lib/kumi/core/analyzer/passes/type_checker.rb +162 -0
- data/lib/kumi/core/analyzer/passes/type_consistency_checker.rb +48 -0
- data/lib/kumi/core/analyzer/passes/type_inferencer.rb +236 -0
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +406 -0
- data/lib/kumi/core/analyzer/passes/visitor_pass.rb +44 -0
- data/lib/kumi/core/atom_unsat_solver.rb +396 -0
- data/lib/kumi/core/compiled_schema.rb +43 -0
- data/lib/kumi/core/constraint_relationship_solver.rb +641 -0
- data/lib/kumi/core/domain/enum_analyzer.rb +55 -0
- data/lib/kumi/core/domain/range_analyzer.rb +85 -0
- data/lib/kumi/core/domain/validator.rb +82 -0
- data/lib/kumi/core/domain/violation_formatter.rb +42 -0
- data/lib/kumi/core/error_reporter.rb +166 -0
- data/lib/kumi/core/error_reporting.rb +97 -0
- data/lib/kumi/core/errors.rb +120 -0
- data/lib/kumi/core/evaluation_wrapper.rb +40 -0
- data/lib/kumi/core/explain.rb +295 -0
- data/lib/kumi/core/export/deserializer.rb +41 -0
- data/lib/kumi/core/export/errors.rb +14 -0
- data/lib/kumi/core/export/node_builders.rb +142 -0
- data/lib/kumi/core/export/node_registry.rb +54 -0
- data/lib/kumi/core/export/node_serializers.rb +158 -0
- data/lib/kumi/core/export/serializer.rb +25 -0
- data/lib/kumi/core/export.rb +35 -0
- data/lib/kumi/core/function_registry/collection_functions.rb +202 -0
- data/lib/kumi/core/function_registry/comparison_functions.rb +33 -0
- data/lib/kumi/core/function_registry/conditional_functions.rb +38 -0
- data/lib/kumi/core/function_registry/function_builder.rb +95 -0
- data/lib/kumi/core/function_registry/logical_functions.rb +44 -0
- data/lib/kumi/core/function_registry/math_functions.rb +74 -0
- data/lib/kumi/core/function_registry/string_functions.rb +57 -0
- data/lib/kumi/core/function_registry/type_functions.rb +53 -0
- data/lib/kumi/{function_registry.rb → core/function_registry.rb} +28 -36
- data/lib/kumi/core/input/type_matcher.rb +97 -0
- data/lib/kumi/core/input/validator.rb +51 -0
- data/lib/kumi/core/input/violation_creator.rb +52 -0
- data/lib/kumi/core/json_schema/generator.rb +65 -0
- data/lib/kumi/core/json_schema/validator.rb +27 -0
- data/lib/kumi/core/json_schema.rb +16 -0
- data/lib/kumi/core/ruby_parser/build_context.rb +27 -0
- data/lib/kumi/core/ruby_parser/declaration_reference_proxy.rb +38 -0
- data/lib/kumi/core/ruby_parser/dsl.rb +14 -0
- data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +138 -0
- data/lib/kumi/core/ruby_parser/expression_converter.rb +128 -0
- data/lib/kumi/core/ruby_parser/guard_rails.rb +45 -0
- data/lib/kumi/core/ruby_parser/input_builder.rb +127 -0
- data/lib/kumi/core/ruby_parser/input_field_proxy.rb +48 -0
- data/lib/kumi/core/ruby_parser/input_proxy.rb +31 -0
- data/lib/kumi/core/ruby_parser/nested_input.rb +17 -0
- data/lib/kumi/core/ruby_parser/parser.rb +71 -0
- data/lib/kumi/core/ruby_parser/schema_builder.rb +175 -0
- data/lib/kumi/core/ruby_parser/sugar.rb +263 -0
- data/lib/kumi/core/ruby_parser.rb +12 -0
- data/lib/kumi/core/schema_instance.rb +111 -0
- data/lib/kumi/core/types/builder.rb +23 -0
- data/lib/kumi/core/types/compatibility.rb +96 -0
- data/lib/kumi/core/types/formatter.rb +26 -0
- data/lib/kumi/core/types/inference.rb +42 -0
- data/lib/kumi/core/types/normalizer.rb +72 -0
- data/lib/kumi/core/types/validator.rb +37 -0
- data/lib/kumi/core/types.rb +66 -0
- data/lib/kumi/core/vectorization_metadata.rb +110 -0
- data/lib/kumi/errors.rb +1 -112
- data/lib/kumi/registry.rb +37 -0
- data/lib/kumi/schema.rb +5 -5
- data/lib/kumi/schema_metadata.rb +3 -3
- data/lib/kumi/support/s_expression_printer.rb +161 -0
- data/lib/kumi/syntax/array_expression.rb +6 -6
- data/lib/kumi/syntax/call_expression.rb +4 -4
- data/lib/kumi/syntax/cascade_expression.rb +4 -4
- data/lib/kumi/syntax/case_expression.rb +4 -4
- data/lib/kumi/syntax/declaration_reference.rb +4 -4
- data/lib/kumi/syntax/hash_expression.rb +4 -4
- data/lib/kumi/syntax/input_declaration.rb +5 -5
- data/lib/kumi/syntax/input_element_reference.rb +5 -5
- data/lib/kumi/syntax/input_reference.rb +5 -5
- data/lib/kumi/syntax/literal.rb +4 -4
- data/lib/kumi/syntax/node.rb +34 -34
- data/lib/kumi/syntax/root.rb +6 -6
- data/lib/kumi/syntax/trait_declaration.rb +4 -4
- data/lib/kumi/syntax/value_declaration.rb +4 -4
- data/lib/kumi/version.rb +1 -1
- data/migrate_to_core_iterative.rb +938 -0
- data/scripts/generate_function_docs.rb +9 -9
- metadata +77 -72
- data/lib/kumi/analyzer/analysis_state.rb +0 -37
- data/lib/kumi/analyzer/constant_evaluator.rb +0 -57
- data/lib/kumi/analyzer/passes/broadcast_detector.rb +0 -246
- data/lib/kumi/analyzer/passes/declaration_validator.rb +0 -43
- data/lib/kumi/analyzer/passes/dependency_resolver.rb +0 -151
- data/lib/kumi/analyzer/passes/input_collector.rb +0 -137
- data/lib/kumi/analyzer/passes/name_indexer.rb +0 -24
- data/lib/kumi/analyzer/passes/pass_base.rb +0 -50
- data/lib/kumi/analyzer/passes/semantic_constraint_validator.rb +0 -109
- data/lib/kumi/analyzer/passes/toposorter.rb +0 -108
- data/lib/kumi/analyzer/passes/type_checker.rb +0 -160
- data/lib/kumi/analyzer/passes/type_consistency_checker.rb +0 -46
- data/lib/kumi/analyzer/passes/type_inferencer.rb +0 -232
- data/lib/kumi/analyzer/passes/unsat_detector.rb +0 -404
- data/lib/kumi/analyzer/passes/visitor_pass.rb +0 -42
- data/lib/kumi/atom_unsat_solver.rb +0 -394
- data/lib/kumi/compiled_schema.rb +0 -41
- data/lib/kumi/constraint_relationship_solver.rb +0 -638
- data/lib/kumi/domain/enum_analyzer.rb +0 -53
- data/lib/kumi/domain/range_analyzer.rb +0 -83
- data/lib/kumi/domain/validator.rb +0 -80
- data/lib/kumi/domain/violation_formatter.rb +0 -40
- data/lib/kumi/error_reporter.rb +0 -164
- data/lib/kumi/error_reporting.rb +0 -95
- data/lib/kumi/evaluation_wrapper.rb +0 -38
- data/lib/kumi/explain.rb +0 -293
- data/lib/kumi/export/deserializer.rb +0 -39
- data/lib/kumi/export/errors.rb +0 -12
- data/lib/kumi/export/node_builders.rb +0 -140
- data/lib/kumi/export/node_registry.rb +0 -52
- data/lib/kumi/export/node_serializers.rb +0 -156
- data/lib/kumi/export/serializer.rb +0 -23
- data/lib/kumi/export.rb +0 -33
- data/lib/kumi/function_registry/collection_functions.rb +0 -200
- data/lib/kumi/function_registry/comparison_functions.rb +0 -31
- data/lib/kumi/function_registry/conditional_functions.rb +0 -36
- data/lib/kumi/function_registry/function_builder.rb +0 -93
- data/lib/kumi/function_registry/logical_functions.rb +0 -42
- data/lib/kumi/function_registry/math_functions.rb +0 -72
- data/lib/kumi/function_registry/string_functions.rb +0 -54
- data/lib/kumi/function_registry/type_functions.rb +0 -51
- data/lib/kumi/input/type_matcher.rb +0 -95
- data/lib/kumi/input/validator.rb +0 -49
- data/lib/kumi/input/violation_creator.rb +0 -50
- data/lib/kumi/json_schema/generator.rb +0 -63
- data/lib/kumi/json_schema/validator.rb +0 -25
- data/lib/kumi/json_schema.rb +0 -14
- data/lib/kumi/ruby_parser/build_context.rb +0 -25
- data/lib/kumi/ruby_parser/declaration_reference_proxy.rb +0 -36
- data/lib/kumi/ruby_parser/dsl.rb +0 -12
- data/lib/kumi/ruby_parser/dsl_cascade_builder.rb +0 -136
- data/lib/kumi/ruby_parser/expression_converter.rb +0 -126
- data/lib/kumi/ruby_parser/guard_rails.rb +0 -43
- data/lib/kumi/ruby_parser/input_builder.rb +0 -125
- data/lib/kumi/ruby_parser/input_field_proxy.rb +0 -46
- data/lib/kumi/ruby_parser/input_proxy.rb +0 -29
- data/lib/kumi/ruby_parser/nested_input.rb +0 -15
- data/lib/kumi/ruby_parser/parser.rb +0 -69
- data/lib/kumi/ruby_parser/schema_builder.rb +0 -173
- data/lib/kumi/ruby_parser/sugar.rb +0 -261
- data/lib/kumi/ruby_parser.rb +0 -10
- data/lib/kumi/schema_instance.rb +0 -109
- data/lib/kumi/types/builder.rb +0 -21
- data/lib/kumi/types/compatibility.rb +0 -94
- data/lib/kumi/types/formatter.rb +0 -24
- data/lib/kumi/types/inference.rb +0 -40
- data/lib/kumi/types/normalizer.rb +0 -70
- data/lib/kumi/types/validator.rb +0 -35
- data/lib/kumi/types.rb +0 -64
- data/lib/kumi/vectorization_metadata.rb +0 -108
@@ -9,7 +9,7 @@ require "kumi"
|
|
9
9
|
|
10
10
|
# Helper to format the type information for display.
|
11
11
|
def format_type(type)
|
12
|
-
Kumi::Types.type_to_s(type)
|
12
|
+
Kumi::Core::Types.type_to_s(type)
|
13
13
|
end
|
14
14
|
|
15
15
|
# Helper to generate a signature string for a function.
|
@@ -49,19 +49,19 @@ end
|
|
49
49
|
|
50
50
|
def function_categories
|
51
51
|
{
|
52
|
-
"Logical Functions" => Kumi::
|
53
|
-
"Comparison Functions" => Kumi::
|
54
|
-
"Math Functions" => Kumi::
|
55
|
-
"String Functions" => Kumi::
|
56
|
-
"Collection Functions" => Kumi::
|
57
|
-
"Conditional Functions" => Kumi::
|
58
|
-
"Type & Hash Functions" => Kumi::
|
52
|
+
"Logical Functions" => Kumi::Registry.logical_operations,
|
53
|
+
"Comparison Functions" => Kumi::Registry.comparison_operators,
|
54
|
+
"Math Functions" => Kumi::Registry.math_operations,
|
55
|
+
"String Functions" => Kumi::Registry.string_operations,
|
56
|
+
"Collection Functions" => Kumi::Registry.collection_operations,
|
57
|
+
"Conditional Functions" => Kumi::Registry.conditional_operations,
|
58
|
+
"Type & Hash Functions" => Kumi::Registry.type_operations
|
59
59
|
}
|
60
60
|
end
|
61
61
|
|
62
62
|
def add_functions_for_category(output, functions)
|
63
63
|
functions.sort.each do |name|
|
64
|
-
signature = Kumi::
|
64
|
+
signature = Kumi::Registry.signature(name)
|
65
65
|
output << "* **`#{name}`**: #{signature[:description]}"
|
66
66
|
output << " * **Usage**: #{generate_signature(name, signature)}"
|
67
67
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- André Muta
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- docs/features/array-broadcasting.md
|
49
49
|
- docs/features/input-declaration-system.md
|
50
50
|
- docs/features/performance.md
|
51
|
+
- docs/features/s-expression-printer.md
|
51
52
|
- docs/schema_metadata.md
|
52
53
|
- docs/schema_metadata/broadcasts.md
|
53
54
|
- docs/schema_metadata/cascades.md
|
@@ -65,74 +66,85 @@ files:
|
|
65
66
|
- examples/wide_schema_compilation_and_evaluation_benchmark.rb
|
66
67
|
- lib/kumi.rb
|
67
68
|
- lib/kumi/analyzer.rb
|
68
|
-
- lib/kumi/analyzer/analysis_state.rb
|
69
|
-
- lib/kumi/analyzer/constant_evaluator.rb
|
70
|
-
- lib/kumi/analyzer/passes/broadcast_detector.rb
|
71
|
-
- lib/kumi/analyzer/passes/declaration_validator.rb
|
72
|
-
- lib/kumi/analyzer/passes/dependency_resolver.rb
|
73
|
-
- lib/kumi/analyzer/passes/input_collector.rb
|
74
|
-
- lib/kumi/analyzer/passes/name_indexer.rb
|
75
|
-
- lib/kumi/analyzer/passes/pass_base.rb
|
76
|
-
- lib/kumi/analyzer/passes/semantic_constraint_validator.rb
|
77
|
-
- lib/kumi/analyzer/passes/toposorter.rb
|
78
|
-
- lib/kumi/analyzer/passes/type_checker.rb
|
79
|
-
- lib/kumi/analyzer/passes/type_consistency_checker.rb
|
80
|
-
- lib/kumi/analyzer/passes/type_inferencer.rb
|
81
|
-
- lib/kumi/analyzer/passes/unsat_detector.rb
|
82
|
-
- lib/kumi/analyzer/passes/visitor_pass.rb
|
83
|
-
- lib/kumi/atom_unsat_solver.rb
|
84
69
|
- lib/kumi/cli.rb
|
85
|
-
- lib/kumi/compiled_schema.rb
|
86
70
|
- lib/kumi/compiler.rb
|
87
|
-
- lib/kumi/
|
88
|
-
- lib/kumi/
|
89
|
-
- lib/kumi/
|
90
|
-
- lib/kumi/
|
91
|
-
- lib/kumi/
|
92
|
-
- lib/kumi/
|
93
|
-
- lib/kumi/
|
71
|
+
- lib/kumi/core/analyzer/analysis_state.rb
|
72
|
+
- lib/kumi/core/analyzer/constant_evaluator.rb
|
73
|
+
- lib/kumi/core/analyzer/passes/broadcast_detector.rb
|
74
|
+
- lib/kumi/core/analyzer/passes/declaration_validator.rb
|
75
|
+
- lib/kumi/core/analyzer/passes/dependency_resolver.rb
|
76
|
+
- lib/kumi/core/analyzer/passes/input_collector.rb
|
77
|
+
- lib/kumi/core/analyzer/passes/name_indexer.rb
|
78
|
+
- lib/kumi/core/analyzer/passes/pass_base.rb
|
79
|
+
- lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb
|
80
|
+
- lib/kumi/core/analyzer/passes/toposorter.rb
|
81
|
+
- lib/kumi/core/analyzer/passes/type_checker.rb
|
82
|
+
- lib/kumi/core/analyzer/passes/type_consistency_checker.rb
|
83
|
+
- lib/kumi/core/analyzer/passes/type_inferencer.rb
|
84
|
+
- lib/kumi/core/analyzer/passes/unsat_detector.rb
|
85
|
+
- lib/kumi/core/analyzer/passes/visitor_pass.rb
|
86
|
+
- lib/kumi/core/atom_unsat_solver.rb
|
87
|
+
- lib/kumi/core/compiled_schema.rb
|
88
|
+
- lib/kumi/core/constraint_relationship_solver.rb
|
89
|
+
- lib/kumi/core/domain/enum_analyzer.rb
|
90
|
+
- lib/kumi/core/domain/range_analyzer.rb
|
91
|
+
- lib/kumi/core/domain/validator.rb
|
92
|
+
- lib/kumi/core/domain/violation_formatter.rb
|
93
|
+
- lib/kumi/core/error_reporter.rb
|
94
|
+
- lib/kumi/core/error_reporting.rb
|
95
|
+
- lib/kumi/core/errors.rb
|
96
|
+
- lib/kumi/core/evaluation_wrapper.rb
|
97
|
+
- lib/kumi/core/explain.rb
|
98
|
+
- lib/kumi/core/export.rb
|
99
|
+
- lib/kumi/core/export/deserializer.rb
|
100
|
+
- lib/kumi/core/export/errors.rb
|
101
|
+
- lib/kumi/core/export/node_builders.rb
|
102
|
+
- lib/kumi/core/export/node_registry.rb
|
103
|
+
- lib/kumi/core/export/node_serializers.rb
|
104
|
+
- lib/kumi/core/export/serializer.rb
|
105
|
+
- lib/kumi/core/function_registry.rb
|
106
|
+
- lib/kumi/core/function_registry/collection_functions.rb
|
107
|
+
- lib/kumi/core/function_registry/comparison_functions.rb
|
108
|
+
- lib/kumi/core/function_registry/conditional_functions.rb
|
109
|
+
- lib/kumi/core/function_registry/function_builder.rb
|
110
|
+
- lib/kumi/core/function_registry/logical_functions.rb
|
111
|
+
- lib/kumi/core/function_registry/math_functions.rb
|
112
|
+
- lib/kumi/core/function_registry/string_functions.rb
|
113
|
+
- lib/kumi/core/function_registry/type_functions.rb
|
114
|
+
- lib/kumi/core/input/type_matcher.rb
|
115
|
+
- lib/kumi/core/input/validator.rb
|
116
|
+
- lib/kumi/core/input/violation_creator.rb
|
117
|
+
- lib/kumi/core/json_schema.rb
|
118
|
+
- lib/kumi/core/json_schema/generator.rb
|
119
|
+
- lib/kumi/core/json_schema/validator.rb
|
120
|
+
- lib/kumi/core/ruby_parser.rb
|
121
|
+
- lib/kumi/core/ruby_parser/build_context.rb
|
122
|
+
- lib/kumi/core/ruby_parser/declaration_reference_proxy.rb
|
123
|
+
- lib/kumi/core/ruby_parser/dsl.rb
|
124
|
+
- lib/kumi/core/ruby_parser/dsl_cascade_builder.rb
|
125
|
+
- lib/kumi/core/ruby_parser/expression_converter.rb
|
126
|
+
- lib/kumi/core/ruby_parser/guard_rails.rb
|
127
|
+
- lib/kumi/core/ruby_parser/input_builder.rb
|
128
|
+
- lib/kumi/core/ruby_parser/input_field_proxy.rb
|
129
|
+
- lib/kumi/core/ruby_parser/input_proxy.rb
|
130
|
+
- lib/kumi/core/ruby_parser/nested_input.rb
|
131
|
+
- lib/kumi/core/ruby_parser/parser.rb
|
132
|
+
- lib/kumi/core/ruby_parser/schema_builder.rb
|
133
|
+
- lib/kumi/core/ruby_parser/sugar.rb
|
134
|
+
- lib/kumi/core/schema_instance.rb
|
135
|
+
- lib/kumi/core/types.rb
|
136
|
+
- lib/kumi/core/types/builder.rb
|
137
|
+
- lib/kumi/core/types/compatibility.rb
|
138
|
+
- lib/kumi/core/types/formatter.rb
|
139
|
+
- lib/kumi/core/types/inference.rb
|
140
|
+
- lib/kumi/core/types/normalizer.rb
|
141
|
+
- lib/kumi/core/types/validator.rb
|
142
|
+
- lib/kumi/core/vectorization_metadata.rb
|
94
143
|
- lib/kumi/errors.rb
|
95
|
-
- lib/kumi/
|
96
|
-
- lib/kumi/explain.rb
|
97
|
-
- lib/kumi/export.rb
|
98
|
-
- lib/kumi/export/deserializer.rb
|
99
|
-
- lib/kumi/export/errors.rb
|
100
|
-
- lib/kumi/export/node_builders.rb
|
101
|
-
- lib/kumi/export/node_registry.rb
|
102
|
-
- lib/kumi/export/node_serializers.rb
|
103
|
-
- lib/kumi/export/serializer.rb
|
104
|
-
- lib/kumi/function_registry.rb
|
105
|
-
- lib/kumi/function_registry/collection_functions.rb
|
106
|
-
- lib/kumi/function_registry/comparison_functions.rb
|
107
|
-
- lib/kumi/function_registry/conditional_functions.rb
|
108
|
-
- lib/kumi/function_registry/function_builder.rb
|
109
|
-
- lib/kumi/function_registry/logical_functions.rb
|
110
|
-
- lib/kumi/function_registry/math_functions.rb
|
111
|
-
- lib/kumi/function_registry/string_functions.rb
|
112
|
-
- lib/kumi/function_registry/type_functions.rb
|
113
|
-
- lib/kumi/input/type_matcher.rb
|
114
|
-
- lib/kumi/input/validator.rb
|
115
|
-
- lib/kumi/input/violation_creator.rb
|
116
|
-
- lib/kumi/json_schema.rb
|
117
|
-
- lib/kumi/json_schema/generator.rb
|
118
|
-
- lib/kumi/json_schema/validator.rb
|
119
|
-
- lib/kumi/ruby_parser.rb
|
120
|
-
- lib/kumi/ruby_parser/build_context.rb
|
121
|
-
- lib/kumi/ruby_parser/declaration_reference_proxy.rb
|
122
|
-
- lib/kumi/ruby_parser/dsl.rb
|
123
|
-
- lib/kumi/ruby_parser/dsl_cascade_builder.rb
|
124
|
-
- lib/kumi/ruby_parser/expression_converter.rb
|
125
|
-
- lib/kumi/ruby_parser/guard_rails.rb
|
126
|
-
- lib/kumi/ruby_parser/input_builder.rb
|
127
|
-
- lib/kumi/ruby_parser/input_field_proxy.rb
|
128
|
-
- lib/kumi/ruby_parser/input_proxy.rb
|
129
|
-
- lib/kumi/ruby_parser/nested_input.rb
|
130
|
-
- lib/kumi/ruby_parser/parser.rb
|
131
|
-
- lib/kumi/ruby_parser/schema_builder.rb
|
132
|
-
- lib/kumi/ruby_parser/sugar.rb
|
144
|
+
- lib/kumi/registry.rb
|
133
145
|
- lib/kumi/schema.rb
|
134
|
-
- lib/kumi/schema_instance.rb
|
135
146
|
- lib/kumi/schema_metadata.rb
|
147
|
+
- lib/kumi/support/s_expression_printer.rb
|
136
148
|
- lib/kumi/syntax/array_expression.rb
|
137
149
|
- lib/kumi/syntax/call_expression.rb
|
138
150
|
- lib/kumi/syntax/cascade_expression.rb
|
@@ -147,15 +159,8 @@ files:
|
|
147
159
|
- lib/kumi/syntax/root.rb
|
148
160
|
- lib/kumi/syntax/trait_declaration.rb
|
149
161
|
- lib/kumi/syntax/value_declaration.rb
|
150
|
-
- lib/kumi/types.rb
|
151
|
-
- lib/kumi/types/builder.rb
|
152
|
-
- lib/kumi/types/compatibility.rb
|
153
|
-
- lib/kumi/types/formatter.rb
|
154
|
-
- lib/kumi/types/inference.rb
|
155
|
-
- lib/kumi/types/normalizer.rb
|
156
|
-
- lib/kumi/types/validator.rb
|
157
|
-
- lib/kumi/vectorization_metadata.rb
|
158
162
|
- lib/kumi/version.rb
|
163
|
+
- migrate_to_core_iterative.rb
|
159
164
|
- scripts/generate_function_docs.rb
|
160
165
|
homepage: https://github.com/amuta/kumi
|
161
166
|
licenses:
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module Analyzer
|
5
|
-
# Simple immutable state wrapper to prevent accidental mutations between passes
|
6
|
-
class AnalysisState
|
7
|
-
def initialize(data = {})
|
8
|
-
@data = data.dup.freeze
|
9
|
-
end
|
10
|
-
|
11
|
-
# Get a value (same as hash access)
|
12
|
-
def [](key)
|
13
|
-
@data[key]
|
14
|
-
end
|
15
|
-
|
16
|
-
# Check if key exists (same as hash)
|
17
|
-
def key?(key)
|
18
|
-
@data.key?(key)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Get all keys (same as hash)
|
22
|
-
def keys
|
23
|
-
@data.keys
|
24
|
-
end
|
25
|
-
|
26
|
-
# Create new state with additional data (simple and clean)
|
27
|
-
def with(key, value)
|
28
|
-
AnalysisState.new(@data.merge(key => value))
|
29
|
-
end
|
30
|
-
|
31
|
-
# Convert back to hash for final result
|
32
|
-
def to_h
|
33
|
-
@data.dup
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module Analyzer
|
5
|
-
class ConstantEvaluator
|
6
|
-
include Syntax
|
7
|
-
|
8
|
-
def initialize(definitions)
|
9
|
-
@definitions = definitions
|
10
|
-
@memo = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
OPERATORS = {
|
14
|
-
add: :+,
|
15
|
-
subtract: :-,
|
16
|
-
multiply: :*,
|
17
|
-
divide: :/
|
18
|
-
}.freeze
|
19
|
-
|
20
|
-
def evaluate(node, visited = Set.new)
|
21
|
-
return :unknown unless node
|
22
|
-
return @memo[node] if @memo.key?(node)
|
23
|
-
return node.value if node.is_a?(Literal)
|
24
|
-
|
25
|
-
result = case node
|
26
|
-
when DeclarationReference then evaluate_binding(node, visited)
|
27
|
-
when CallExpression then evaluate_call_expression(node, visited)
|
28
|
-
else :unknown
|
29
|
-
end
|
30
|
-
|
31
|
-
@memo[node] = result unless result == :unknown
|
32
|
-
result
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def evaluate_binding(node, visited)
|
38
|
-
return :unknown if visited.include?(node.name)
|
39
|
-
|
40
|
-
visited << node.name
|
41
|
-
definition = @definitions[node.name]
|
42
|
-
return :unknown unless definition
|
43
|
-
|
44
|
-
evaluate(definition.expression, visited)
|
45
|
-
end
|
46
|
-
|
47
|
-
def evaluate_call_expression(node, visited)
|
48
|
-
return :unknown unless OPERATORS.key?(node.fn_name)
|
49
|
-
|
50
|
-
args = node.args.map { |arg| evaluate(arg, visited) }
|
51
|
-
return :unknown if args.any?(:unknown)
|
52
|
-
|
53
|
-
args.reduce(OPERATORS[node.fn_name])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module Analyzer
|
5
|
-
module Passes
|
6
|
-
# Detects which operations should be broadcast over arrays
|
7
|
-
# DEPENDENCIES: :inputs, :declarations
|
8
|
-
# PRODUCES: :broadcasts
|
9
|
-
class BroadcastDetector < PassBase
|
10
|
-
def run(errors)
|
11
|
-
input_meta = get_state(:inputs) || {}
|
12
|
-
definitions = get_state(:declarations) || {}
|
13
|
-
|
14
|
-
# Find array fields with their element types
|
15
|
-
array_fields = find_array_fields(input_meta)
|
16
|
-
|
17
|
-
# Build compiler metadata
|
18
|
-
compiler_metadata = {
|
19
|
-
array_fields: array_fields,
|
20
|
-
vectorized_operations: {},
|
21
|
-
reduction_operations: {}
|
22
|
-
}
|
23
|
-
|
24
|
-
# Track which values are vectorized for type inference
|
25
|
-
vectorized_values = {}
|
26
|
-
|
27
|
-
# Analyze traits first, then values (to handle dependencies)
|
28
|
-
traits = definitions.select { |_name, decl| decl.is_a?(Kumi::Syntax::TraitDeclaration) }
|
29
|
-
values = definitions.select { |_name, decl| decl.is_a?(Kumi::Syntax::ValueDeclaration) }
|
30
|
-
|
31
|
-
(traits.to_a + values.to_a).each do |name, decl|
|
32
|
-
result = analyze_value_vectorization(name, decl.expression, array_fields, vectorized_values, errors)
|
33
|
-
|
34
|
-
case result[:type]
|
35
|
-
when :vectorized
|
36
|
-
compiler_metadata[:vectorized_operations][name] = result[:info]
|
37
|
-
# Store array source information for dimension checking
|
38
|
-
array_source = extract_array_source(result[:info], array_fields)
|
39
|
-
vectorized_values[name] = { vectorized: true, array_source: array_source }
|
40
|
-
when :reduction
|
41
|
-
compiler_metadata[:reduction_operations][name] = result[:info]
|
42
|
-
# Reduction produces scalar, not vectorized
|
43
|
-
vectorized_values[name] = { vectorized: false }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
state.with(:broadcasts, compiler_metadata.freeze)
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def find_array_fields(input_meta)
|
53
|
-
result = {}
|
54
|
-
input_meta.each do |name, meta|
|
55
|
-
next unless meta[:type] == :array && meta[:children]
|
56
|
-
|
57
|
-
result[name] = {
|
58
|
-
element_fields: meta[:children].keys,
|
59
|
-
element_types: meta[:children].transform_values { |v| v[:type] || :any }
|
60
|
-
}
|
61
|
-
end
|
62
|
-
result
|
63
|
-
end
|
64
|
-
|
65
|
-
def analyze_value_vectorization(name, expr, array_fields, vectorized_values, errors)
|
66
|
-
case expr
|
67
|
-
when Kumi::Syntax::InputElementReference
|
68
|
-
if array_fields.key?(expr.path.first)
|
69
|
-
{ type: :vectorized, info: { source: :array_field_access, path: expr.path } }
|
70
|
-
else
|
71
|
-
{ type: :scalar }
|
72
|
-
end
|
73
|
-
|
74
|
-
when Kumi::Syntax::DeclarationReference
|
75
|
-
# Check if this references a vectorized value
|
76
|
-
vector_info = vectorized_values[expr.name]
|
77
|
-
if vector_info && vector_info[:vectorized]
|
78
|
-
{ type: :vectorized, info: { source: :vectorized_declaration, name: expr.name } }
|
79
|
-
else
|
80
|
-
{ type: :scalar }
|
81
|
-
end
|
82
|
-
|
83
|
-
when Kumi::Syntax::CallExpression
|
84
|
-
analyze_call_vectorization(name, expr, array_fields, vectorized_values, errors)
|
85
|
-
|
86
|
-
when Kumi::Syntax::CascadeExpression
|
87
|
-
analyze_cascade_vectorization(name, expr, array_fields, vectorized_values, errors)
|
88
|
-
|
89
|
-
else
|
90
|
-
{ type: :scalar }
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def analyze_call_vectorization(_name, expr, array_fields, vectorized_values, errors)
|
95
|
-
# Check if this is a reduction function using function registry metadata
|
96
|
-
if FunctionRegistry.reducer?(expr.fn_name)
|
97
|
-
# Only treat as reduction if the argument is actually vectorized
|
98
|
-
arg_info = analyze_argument_vectorization(expr.args.first, array_fields, vectorized_values)
|
99
|
-
if arg_info[:vectorized]
|
100
|
-
{ type: :reduction, info: { function: expr.fn_name, source: arg_info[:source] } }
|
101
|
-
else
|
102
|
-
# Not a vectorized reduction - just a regular function call
|
103
|
-
{ type: :scalar }
|
104
|
-
end
|
105
|
-
|
106
|
-
else
|
107
|
-
# Special case: all?, any?, none? functions with vectorized trait arguments should be treated as vectorized
|
108
|
-
# for cascade condition purposes (they get transformed during compilation)
|
109
|
-
if %i[all? any? none?].include?(expr.fn_name) && expr.args.length == 1
|
110
|
-
arg = expr.args.first
|
111
|
-
if arg.is_a?(Kumi::Syntax::ArrayExpression) && arg.elements.length == 1
|
112
|
-
trait_ref = arg.elements.first
|
113
|
-
if trait_ref.is_a?(Kumi::Syntax::DeclarationReference) && vectorized_values[trait_ref.name]&.[](:vectorized)
|
114
|
-
return { type: :vectorized, info: { source: :cascade_condition_with_vectorized_trait, trait: trait_ref.name } }
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# ANY function with vectorized arguments becomes vectorized (with broadcasting)
|
120
|
-
arg_infos = expr.args.map { |arg| analyze_argument_vectorization(arg, array_fields, vectorized_values) }
|
121
|
-
|
122
|
-
if arg_infos.any? { |info| info[:vectorized] }
|
123
|
-
# Check for dimension mismatches when multiple arguments are vectorized
|
124
|
-
vectorized_sources = arg_infos.select { |info| info[:vectorized] }.filter_map { |info| info[:array_source] }.uniq
|
125
|
-
|
126
|
-
if vectorized_sources.length > 1
|
127
|
-
# Multiple different array sources - this is a dimension mismatch
|
128
|
-
# Generate enhanced error message with type information
|
129
|
-
enhanced_message = build_dimension_mismatch_error(expr, arg_infos, array_fields, vectorized_sources)
|
130
|
-
|
131
|
-
report_error(errors, enhanced_message, location: expr.loc, type: :semantic)
|
132
|
-
return { type: :scalar } # Treat as scalar to prevent further errors
|
133
|
-
end
|
134
|
-
|
135
|
-
# This is a vectorized operation - ANY function supports broadcasting
|
136
|
-
{ type: :vectorized, info: {
|
137
|
-
operation: expr.fn_name,
|
138
|
-
vectorized_args: arg_infos.map.with_index { |info, i| [i, info[:vectorized]] }.to_h
|
139
|
-
} }
|
140
|
-
else
|
141
|
-
{ type: :scalar }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def analyze_argument_vectorization(arg, array_fields, vectorized_values)
|
147
|
-
case arg
|
148
|
-
when Kumi::Syntax::InputElementReference
|
149
|
-
if array_fields.key?(arg.path.first)
|
150
|
-
{ vectorized: true, source: :array_field, array_source: arg.path.first }
|
151
|
-
else
|
152
|
-
{ vectorized: false }
|
153
|
-
end
|
154
|
-
|
155
|
-
when Kumi::Syntax::DeclarationReference
|
156
|
-
# Check if this references a vectorized value
|
157
|
-
vector_info = vectorized_values[arg.name]
|
158
|
-
if vector_info && vector_info[:vectorized]
|
159
|
-
array_source = vector_info[:array_source]
|
160
|
-
{ vectorized: true, source: :vectorized_value, array_source: array_source }
|
161
|
-
else
|
162
|
-
{ vectorized: false }
|
163
|
-
end
|
164
|
-
|
165
|
-
when Kumi::Syntax::CallExpression
|
166
|
-
# Recursively check
|
167
|
-
result = analyze_value_vectorization(nil, arg, array_fields, vectorized_values, [])
|
168
|
-
{ vectorized: result[:type] == :vectorized, source: :expression }
|
169
|
-
|
170
|
-
else
|
171
|
-
{ vectorized: false }
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def extract_array_source(info, _array_fields)
|
176
|
-
case info[:source]
|
177
|
-
when :array_field_access
|
178
|
-
info[:path]&.first
|
179
|
-
when :cascade_condition_with_vectorized_trait
|
180
|
-
# For cascades, we'd need to trace back to the original source
|
181
|
-
nil # TODO: Could be enhanced to trace through trait dependencies
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def analyze_cascade_vectorization(_name, expr, array_fields, vectorized_values, errors)
|
186
|
-
# A cascade is vectorized if:
|
187
|
-
# 1. Any of its result expressions are vectorized, OR
|
188
|
-
# 2. Any of its conditions reference vectorized values (traits or arrays)
|
189
|
-
vectorized_results = []
|
190
|
-
vectorized_conditions = []
|
191
|
-
|
192
|
-
expr.cases.each do |case_expr|
|
193
|
-
# Check if result is vectorized
|
194
|
-
result_info = analyze_value_vectorization(nil, case_expr.result, array_fields, vectorized_values, errors)
|
195
|
-
vectorized_results << (result_info[:type] == :vectorized)
|
196
|
-
|
197
|
-
# Check if condition is vectorized
|
198
|
-
condition_info = analyze_value_vectorization(nil, case_expr.condition, array_fields, vectorized_values, errors)
|
199
|
-
vectorized_conditions << (condition_info[:type] == :vectorized)
|
200
|
-
end
|
201
|
-
|
202
|
-
if vectorized_results.any? || vectorized_conditions.any?
|
203
|
-
{ type: :vectorized, info: { source: :cascade_with_vectorized_conditions_or_results } }
|
204
|
-
else
|
205
|
-
{ type: :scalar }
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def build_dimension_mismatch_error(_expr, arg_infos, array_fields, vectorized_sources)
|
210
|
-
# Build detailed error message with type information
|
211
|
-
summary = "Cannot broadcast operation across arrays from different sources: #{vectorized_sources.join(', ')}. "
|
212
|
-
|
213
|
-
problem_desc = "Problem: Multiple operands are arrays from different sources:\n"
|
214
|
-
|
215
|
-
vectorized_args = arg_infos.select { |info| info[:vectorized] }
|
216
|
-
vectorized_args.each_with_index do |arg_info, index|
|
217
|
-
array_source = arg_info[:array_source]
|
218
|
-
next unless array_source && array_fields[array_source]
|
219
|
-
|
220
|
-
# Determine the type based on array field metadata
|
221
|
-
type_desc = determine_array_type(array_source, array_fields)
|
222
|
-
problem_desc += " - Operand #{index + 1} resolves to #{type_desc} from array '#{array_source}'\n"
|
223
|
-
end
|
224
|
-
|
225
|
-
explanation = "Direct operations on arrays from different sources is ambiguous and not supported. " \
|
226
|
-
"Vectorized operations can only work on fields from the same array input."
|
227
|
-
|
228
|
-
"#{summary}#{problem_desc}#{explanation}"
|
229
|
-
end
|
230
|
-
|
231
|
-
def determine_array_type(array_source, array_fields)
|
232
|
-
field_info = array_fields[array_source]
|
233
|
-
return "array(any)" unless field_info[:element_types]
|
234
|
-
|
235
|
-
# For nested arrays (like items.name where items is an array), this represents array(element_type)
|
236
|
-
element_types = field_info[:element_types].values.uniq
|
237
|
-
if element_types.length == 1
|
238
|
-
"array(#{element_types.first})"
|
239
|
-
else
|
240
|
-
"array(mixed)"
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module Analyzer
|
5
|
-
module Passes
|
6
|
-
# RESPONSIBILITY: Perform local structural validation on each declaration
|
7
|
-
# DEPENDENCIES: :definitions
|
8
|
-
# PRODUCES: None (validation only)
|
9
|
-
# INTERFACE: new(schema, state).run(errors)
|
10
|
-
class DeclarationValidator < VisitorPass
|
11
|
-
def run(errors)
|
12
|
-
each_decl do |decl|
|
13
|
-
visit(decl) { |node| validate_node(node, errors) }
|
14
|
-
end
|
15
|
-
state
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def validate_node(node, errors)
|
21
|
-
case node
|
22
|
-
when Kumi::Syntax::ValueDeclaration
|
23
|
-
validate_attribute(node, errors)
|
24
|
-
when Kumi::Syntax::TraitDeclaration
|
25
|
-
validate_trait(node, errors)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def validate_attribute(node, errors)
|
30
|
-
return unless node.expression.nil?
|
31
|
-
|
32
|
-
report_error(errors, "attribute `#{node.name}` requires an expression", location: node.loc)
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate_trait(node, errors)
|
36
|
-
return if node.expression.is_a?(Kumi::Syntax::CallExpression)
|
37
|
-
|
38
|
-
report_error(errors, "trait `#{node.name}` must wrap a CallExpression", location: node.loc)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|