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
@@ -0,0 +1,57 @@
1
+ # Dependencies Metadata
2
+
3
+ Processed dependency information showing relationships between declarations with clean, serializable data.
4
+
5
+ ## Access
6
+
7
+ ```ruby
8
+ metadata = MySchema.schema_metadata
9
+ dependencies = metadata.dependencies
10
+ ```
11
+
12
+ ## Structure
13
+
14
+ ```ruby
15
+ # Returns Hash<Symbol, Array<Hash>>
16
+ {
17
+ declaration_name => [
18
+ {
19
+ to: Symbol, # Target declaration name
20
+ conditional: Boolean, # True if dependency is conditional (cascade branch)
21
+ cascade_owner: Symbol # Optional: cascade that owns this conditional edge
22
+ }
23
+ ]
24
+ }
25
+ ```
26
+
27
+ ## Example
28
+
29
+ ```ruby
30
+ metadata.dependencies
31
+ # => {
32
+ # :tax_amount => [
33
+ # { to: :income, conditional: false },
34
+ # { to: :deductions, conditional: false }
35
+ # ],
36
+ # :status => [
37
+ # { to: :adult, conditional: true, cascade_owner: :status },
38
+ # { to: :verified, conditional: true, cascade_owner: :status }
39
+ # ]
40
+ # }
41
+ ```
42
+
43
+ ## Raw Edge Objects
44
+
45
+ For advanced use cases requiring direct Edge object access:
46
+
47
+ ```ruby
48
+ raw_dependencies = metadata.analyzer_state[:dependencies]
49
+ # => { :tax_amount => [#<Edge to: :income>, #<Edge to: :deductions>] }
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ - Topological sorting
55
+ - Cycle detection
56
+ - Evaluation planning
57
+ - Dependency visualization
@@ -0,0 +1,29 @@
1
+ # Evaluation Order Metadata
2
+
3
+ Topologically sorted order for safe declaration evaluation.
4
+
5
+ ## Structure
6
+
7
+ ```ruby
8
+ state[:evaluation_order] = [:name1, :name2, :name3, ...]
9
+ ```
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ [:income, :deductions, :taxable_income, :tax_rate, :tax_amount, :adult, :status]
15
+ ```
16
+
17
+ ## Properties
18
+
19
+ - Dependencies appear before dependents
20
+ - Handles conditional cycles in cascades
21
+ - Deterministic ordering
22
+ - Leaf nodes typically appear first
23
+
24
+ ## Usage
25
+
26
+ - Compilation order
27
+ - Evaluation sequencing
28
+ - Optimization planning
29
+ - Parallel execution grouping
@@ -0,0 +1,95 @@
1
+ # Schema Metadata Examples
2
+
3
+ For comprehensive API documentation with detailed examples, see the YARD documentation in the SchemaMetadata class.
4
+
5
+ ## Basic Usage
6
+
7
+ ```ruby
8
+ class TaxSchema
9
+ extend Kumi::Schema
10
+
11
+ schema do
12
+ input do
13
+ integer :income, domain: 0..1_000_000
14
+ string :filing_status, domain: %w[single married]
15
+ integer :age, domain: 18..100
16
+ end
17
+
18
+ trait :adult, (input.age >= 18)
19
+ trait :high_income, (input.income > 100_000)
20
+
21
+ value :tax_rate do
22
+ on high_income, 0.25
23
+ base 0.15
24
+ end
25
+
26
+ value :tax_amount, input.income * tax_rate
27
+ end
28
+ end
29
+
30
+ # Access schema metadata - clean object interface!
31
+ metadata = TaxSchema.schema_metadata
32
+
33
+ # Processed semantic metadata (rich, transformed from AST)
34
+ puts metadata.inputs
35
+ # => { :income => { type: :integer, domain: {...}, required: true }, ... }
36
+
37
+ puts metadata.values
38
+ # => { :tax_rate => { type: :float, cascade: {...} }, ... }
39
+
40
+ puts metadata.traits
41
+ # => { :adult => { type: :boolean, condition: "input.age >= 18" }, ... }
42
+
43
+ # Raw analyzer state (direct from analysis passes)
44
+ puts metadata.evaluation_order
45
+ # => [:adult, :high_income, :tax_rate, :tax_amount]
46
+
47
+ puts metadata.dependencies
48
+ # => { :tax_amount => [#<Edge to: :tax_rate>, #<Edge to: :income>], ... }
49
+
50
+ puts metadata.inferred_types
51
+ # => { :adult => :boolean, :tax_rate => :float, :tax_amount => :float }
52
+
53
+ # Serializable processed hash
54
+ processed_hash = metadata.to_h
55
+ puts processed_hash.keys
56
+ # => [:inputs, :values, :traits, :functions]
57
+
58
+ # Raw analyzer state (contains AST nodes)
59
+ raw_state = metadata.analyzer_state
60
+ puts raw_state.keys
61
+ # => [:declarations, :inputs, :dependencies, :dependents, :leaves, :evaluation_order, :inferred_types, :cascades, :broadcasts]
62
+ ```
63
+
64
+ ## Tool Integration
65
+
66
+ ```ruby
67
+ # Form generator example
68
+ def generate_form_fields(schema_class)
69
+ metadata = schema_class.schema_metadata
70
+
71
+ metadata.inputs.map do |field_name, field_info|
72
+ case field_info[:type]
73
+ when :integer
74
+ create_number_input(field_name, field_info[:domain])
75
+ when :string
76
+ create_select_input(field_name, field_info[:domain])
77
+ when :boolean
78
+ create_checkbox_input(field_name)
79
+ end
80
+ end
81
+ end
82
+
83
+ # Dependency analysis example
84
+ def analyze_field_dependencies(schema_class, field_name)
85
+ metadata = schema_class.schema_metadata
86
+
87
+ # Find what depends on this field
88
+ dependents = metadata.dependents[field_name] || []
89
+
90
+ # Find what this field depends on
91
+ dependencies = metadata.dependencies[field_name]&.map(&:to) || []
92
+
93
+ { affects: dependents, requires: dependencies }
94
+ end
95
+ ```
@@ -0,0 +1,46 @@
1
+ # Inferred Types Metadata
2
+
3
+ Type inference results for all declarations based on expression analysis.
4
+
5
+ ## Access
6
+
7
+ ```ruby
8
+ metadata = MySchema.schema_metadata
9
+ types = metadata.inferred_types
10
+ ```
11
+
12
+ ## Structure
13
+
14
+ ```ruby
15
+ # Returns Hash<Symbol, Object>
16
+ {
17
+ declaration_name => type_specification
18
+ }
19
+ ```
20
+
21
+ ## Example
22
+
23
+ ```ruby
24
+ metadata.inferred_types
25
+ # => {
26
+ # :adult => :boolean,
27
+ # :age_group => :string,
28
+ # :tax_rate => :float,
29
+ # :count => :integer,
30
+ # :item_prices => { array: :float },
31
+ # :categories => { array: :string }
32
+ # }
33
+ ```
34
+
35
+ ## Type Values
36
+
37
+ - `:boolean`, `:string`, `:integer`, `:float`, `:any`
38
+ - `{ array: element_type }` for arrays
39
+ - `{ hash: { key: key_type, value: value_type } }` for hashes
40
+
41
+ ## Usage
42
+
43
+ - Type checking
44
+ - Code generation
45
+ - Editor support
46
+ - Runtime validation
@@ -0,0 +1,86 @@
1
+ # Input Metadata
2
+
3
+ Raw input field metadata extracted from `input` blocks during analysis.
4
+
5
+ ## Access
6
+
7
+ ```ruby
8
+ metadata = MySchema.schema_metadata
9
+
10
+ # Processed input metadata (recommended for tools)
11
+ inputs = metadata.inputs
12
+
13
+ # Raw input metadata (advanced usage)
14
+ raw_inputs = metadata.analyzer_state[:inputs]
15
+ ```
16
+
17
+ ## Raw Structure
18
+
19
+ ```ruby
20
+ # Raw analyzer state format
21
+ {
22
+ field_name => {
23
+ type: Symbol, # :integer, :string, :float, :boolean, :array, etc.
24
+ domain: Range|Array, # optional domain constraints
25
+ children: Hash # for array/hash types
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Processed Structure
31
+
32
+ ```ruby
33
+ # Processed metadata format (via metadata.inputs)
34
+ {
35
+ field_name => {
36
+ type: Symbol, # normalized type
37
+ domain: Hash, # normalized domain metadata
38
+ required: Boolean # always true currently
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## Examples
44
+
45
+ **Processed Input Metadata:**
46
+ ```ruby
47
+ metadata.inputs
48
+ # => {
49
+ # :age => {
50
+ # type: :integer,
51
+ # domain: { type: :range, min: 0, max: 120, exclusive_end: false },
52
+ # required: true
53
+ # },
54
+ # :name => { type: :string, required: true },
55
+ # :active => { type: :boolean, required: true }
56
+ # }
57
+ ```
58
+
59
+ **Raw Input Metadata:**
60
+ ```ruby
61
+ metadata.analyzer_state[:inputs]
62
+ # => {
63
+ # :age => { type: :integer, domain: 0..120 },
64
+ # :name => { type: :string },
65
+ # :line_items => {
66
+ # type: :array,
67
+ # children: {
68
+ # :price => { type: :float, domain: 0..Float::INFINITY },
69
+ # :quantity => { type: :integer, domain: 1..100 }
70
+ # }
71
+ # }
72
+ # }
73
+ ```
74
+
75
+ **Domain Types:**
76
+ - Range: `18..65`, `0..Float::INFINITY`
77
+ - Array: `%w[active inactive suspended]`
78
+ - Proc: Custom validation functions
79
+
80
+ ## Usage
81
+
82
+ Form generators use this metadata to:
83
+ - Create appropriate input controls
84
+ - Set validation rules
85
+ - Build nested forms for arrays
86
+ - Generate type-safe schemas
@@ -0,0 +1,108 @@
1
+ # Schema Metadata
2
+
3
+ Kumi's SchemaMetadata interface provides structured access to analyzed schema information for building external tools like form generators, documentation systems, and analysis utilities.
4
+
5
+ ## Primary Interface
6
+
7
+ SchemaMetadata is the main interface for extracting metadata from Kumi schemas:
8
+
9
+ ```ruby
10
+ metadata = MySchema.schema_metadata
11
+ ```
12
+
13
+ See the comprehensive API documentation in the SchemaMetadata class for detailed method documentation, examples, and usage patterns.
14
+
15
+ ## Processed Metadata (Tool-Friendly)
16
+
17
+ These methods return clean, serializable data structures:
18
+
19
+ | Method | Returns | Description |
20
+ |--------|---------|-------------|
21
+ | `inputs` | Hash | Input field metadata with normalized types and domains |
22
+ | `values` | Hash | Value declarations with dependencies and expressions |
23
+ | `traits` | Hash | Trait conditions with dependency information |
24
+ | `functions` | Hash | Function registry info for functions used in schema |
25
+ | `to_h` | Hash | Complete processed metadata (inputs, values, traits, functions) |
26
+ | `to_json` | String | JSON serialization of processed metadata |
27
+ | `to_json_schema` | Hash | JSON Schema document for input validation |
28
+
29
+ ## Raw Analyzer State (Advanced)
30
+
31
+ Direct access to internal analyzer results:
32
+
33
+ | Method | Returns | Description |
34
+ |--------|---------|-------------|
35
+ | [`declarations`](schema_metadata/declarations.md) | Hash | Raw AST declaration nodes by name |
36
+ | [`dependencies`](schema_metadata/dependencies.md) | Hash | Dependency graph with Edge objects |
37
+ | `dependents` | Hash | Reverse dependency lookup |
38
+ | `leaves` | Hash | Leaf nodes (no dependencies) by type |
39
+ | [`evaluation_order`](schema_metadata/evaluation_order.md) | Array | Topologically sorted evaluation order |
40
+ | [`inferred_types`](schema_metadata/inferred_types.md) | Hash | Type inference results for declarations |
41
+ | [`cascades`](schema_metadata/cascades.md) | Hash | Cascade mutual exclusion analysis |
42
+ | [`broadcasts`](schema_metadata/broadcasts.md) | Hash | Array broadcasting operation metadata |
43
+ | `analyzer_state` | Hash | Complete raw analyzer state with AST nodes |
44
+
45
+ Note: Raw `inputs` metadata is available via `analyzer_state[:inputs]` but the processed `inputs` method is recommended for tool development.
46
+
47
+ ## Usage Patterns
48
+
49
+ ```ruby
50
+ # Tool development - use processed metadata
51
+ metadata = MySchema.schema_metadata
52
+ form_fields = metadata.inputs.map { |name, info| create_field(name, info) }
53
+ documentation = metadata.values.map { |name, info| document_value(name, info) }
54
+
55
+ # Advanced analysis - use raw state when needed
56
+ dependency_graph = metadata.dependencies
57
+ ast_nodes = metadata.declarations
58
+ evaluation_sequence = metadata.evaluation_order
59
+ ```
60
+
61
+ ## Data Structure Examples
62
+
63
+ ### Processed Input Metadata
64
+ ```ruby
65
+ metadata.inputs
66
+ # => {
67
+ # :age => { type: :integer, domain: { type: :range, min: 18, max: 65 }, required: true },
68
+ # :name => { type: :string, required: true },
69
+ # :items => { type: :array, required: true }
70
+ # }
71
+ ```
72
+
73
+ ### Processed Value Metadata
74
+ ```ruby
75
+ metadata.values
76
+ # => {
77
+ # :tax_amount => {
78
+ # type: :float,
79
+ # dependencies: [:income, :tax_rate],
80
+ # computed: true,
81
+ # expression: "multiply(input.income, tax_rate)"
82
+ # }
83
+ # }
84
+ ```
85
+
86
+ ### Clean Public Interface Examples
87
+ ```ruby
88
+ # Processed dependency information (clean hashes)
89
+ metadata.dependencies
90
+ # => { :tax_amount => [{ to: :income, conditional: false }, { to: :tax_rate, conditional: false }] }
91
+
92
+ # Processed declaration metadata (clean hashes)
93
+ metadata.declarations
94
+ # => { :adult => { type: :trait, expression: ">=(input.age, 18)" }, :tax_amount => { type: :value, expression: "multiply(input.income, tax_rate)" } }
95
+
96
+ # Type inference results (clean data)
97
+ metadata.inferred_types
98
+ # => { :adult => :boolean, :tax_amount => :float, :item_totals => { array: :float } }
99
+ ```
100
+
101
+ ### Raw Analyzer State (Advanced Usage)
102
+ ```ruby
103
+ # Complete raw state hash with internal objects (AST nodes, Edge objects)
104
+ metadata.analyzer_state
105
+ # => { declarations: {AST nodes...}, dependencies: {Edge objects...}, ... }
106
+ ```
107
+
108
+ See `docs/schema_metadata/` for detailed examples.
@@ -13,7 +13,7 @@ begin
13
13
  cells[neighbor_index]
14
14
  end.sum
15
15
  end
16
- Kumi::FunctionRegistry.register_with_metadata(:neighbor_cells_sum, method(:neighbor_cells_sum_method),
16
+ Kumi::Core::FunctionRegistry.register_with_metadata(:neighbor_cells_sum, method(:neighbor_cells_sum_method),
17
17
  return_type: :integer, arity: 5,
18
18
  param_types: %i[array integer integer integer integer],
19
19
  description: "Get neighbor cells for Conway's Game of Life")
@@ -22,7 +22,7 @@ begin
22
22
  value :yearly_rate, monthly_rate * 12
23
23
  end
24
24
  end
25
- rescue Kumi::Errors::SemanticError => e
25
+ rescue Kumi::Core::Errors::SemanticError => e
26
26
  puts " → #{e.message}"
27
27
  end
28
28
 
@@ -48,7 +48,7 @@ begin
48
48
  end
49
49
  end
50
50
  end
51
- rescue Kumi::Errors::SemanticError => e
51
+ rescue Kumi::Core::Errors::SemanticError => e
52
52
  puts " → #{e.message}"
53
53
  end
54
54
 
@@ -71,7 +71,7 @@ begin
71
71
  value :invalid_sum, input.name + input.age
72
72
  end
73
73
  end
74
- rescue Kumi::Errors::TypeError => e
74
+ rescue Kumi::Core::Errors::TypeError => e
75
75
  puts " → #{e.message}"
76
76
  end
77
77
 
@@ -94,7 +94,7 @@ begin
94
94
  trait :impossible_score, input.score == 150
95
95
  end
96
96
  end
97
- rescue Kumi::Errors::SemanticError => e
97
+ rescue Kumi::Core::Errors::SemanticError => e
98
98
  puts " → #{e.message}"
99
99
  end
100
100
 
@@ -114,7 +114,7 @@ begin
114
114
  value :result, ref(:nonexistent_trait) ? 100 : 0
115
115
  end
116
116
  end
117
- rescue Kumi::Errors::SemanticError => e
117
+ rescue Kumi::Core::Errors::SemanticError => e
118
118
  puts " → #{e.message}"
119
119
  end
120
120
 
@@ -134,7 +134,7 @@ begin
134
134
  value :result, fn(:nonexistent_function, input.text)
135
135
  end
136
136
  end
137
- rescue Kumi::Errors::TypeError => e
137
+ rescue Kumi::Core::Errors::TypeError => e
138
138
  puts " → #{e.message}"
139
139
  end
140
140
 
@@ -162,7 +162,7 @@ begin
162
162
  value :result, ref(:undefined_declaration)
163
163
  end
164
164
  end
165
- rescue Kumi::Errors::SemanticError => e
165
+ rescue Kumi::Core::Errors::SemanticError => e
166
166
  puts " → " + e.message.split("\n").join("\n → ")
167
167
  end
168
168
 
data/lib/kumi/analyzer.rb CHANGED
@@ -7,21 +7,21 @@ module Kumi
7
7
  module_function
8
8
 
9
9
  DEFAULT_PASSES = [
10
- Passes::NameIndexer, # 1. Finds all names and checks for duplicates.
11
- Passes::InputCollector, # 2. Collects field metadata from input declarations.
12
- Passes::DeclarationValidator, # 3. Checks the basic structure of each rule.
13
- Passes::SemanticConstraintValidator, # 4. Validates DSL semantic constraints at AST level.
14
- Passes::DependencyResolver, # 5. Builds the dependency graph with conditional dependencies.
15
- Passes::UnsatDetector, # 6. Detects unsatisfiable constraints and analyzes cascade mutual exclusion.
16
- Passes::Toposorter, # 7. Creates the final evaluation order, allowing safe cycles.
17
- Passes::BroadcastDetector, # 8. Detects which operations should be broadcast over arrays (must run before type inference).
18
- Passes::TypeInferencer, # 9. Infers types for all declarations (uses vectorization metadata).
19
- Passes::TypeConsistencyChecker, # 10. Validates declared vs inferred type consistency.
20
- Passes::TypeChecker # 11. Validates types using inferred information.
10
+ Core::Analyzer::Passes::NameIndexer, # 1. Finds all names and checks for duplicates.
11
+ Core::Analyzer::Passes::InputCollector, # 2. Collects field metadata from input declarations.
12
+ Core::Analyzer::Passes::DeclarationValidator, # 3. Checks the basic structure of each rule.
13
+ Core::Analyzer::Passes::SemanticConstraintValidator, # 4. Validates DSL semantic constraints at AST level.
14
+ Core::Analyzer::Passes::DependencyResolver, # 5. Builds the dependency graph with conditional dependencies.
15
+ Core::Analyzer::Passes::UnsatDetector, # 6. Detects unsatisfiable constraints and analyzes cascade mutual exclusion.
16
+ Core::Analyzer::Passes::Toposorter, # 7. Creates the final evaluation order, allowing safe cycles.
17
+ Core::Analyzer::Passes::BroadcastDetector, # 8. Detects which operations should be broadcast over arrays (must run before type inference).
18
+ Core::Analyzer::Passes::TypeInferencer, # 9. Infers types for all declarations (uses vectorization metadata).
19
+ Core::Analyzer::Passes::TypeConsistencyChecker, # 10. Validates declared vs inferred type consistency.
20
+ Core::Analyzer::Passes::TypeChecker # 11. Validates types using inferred information.
21
21
  ].freeze
22
22
 
23
- def analyze!(schema, passes: DEFAULT_PASSES, **opts)
24
- state = AnalysisState.new(opts)
23
+ def self.analyze!(schema, passes: DEFAULT_PASSES, **opts)
24
+ state = Core::Analyzer::AnalysisState.new(opts)
25
25
  errors = []
26
26
 
27
27
  state = run_analysis_passes(schema, passes, state, errors)
@@ -35,7 +35,7 @@ module Kumi
35
35
  begin
36
36
  state = pass_instance.run(errors)
37
37
  rescue StandardError => e
38
- errors << ErrorReporter.create_error(e.message, location: nil, type: :semantic)
38
+ errors << Core::ErrorReporter.create_error(e.message, location: nil, type: :semantic)
39
39
  end
40
40
  end
41
41
  state
@@ -52,17 +52,17 @@ module Kumi
52
52
 
53
53
  def self.create_analysis_result(state)
54
54
  Result.new(
55
- definitions: state[:definitions],
56
- dependency_graph: state[:dependency_graph],
57
- leaf_map: state[:leaf_map],
58
- topo_order: state[:topo_order],
59
- decl_types: state[:decl_types],
55
+ definitions: state[:declarations],
56
+ dependency_graph: state[:dependencies],
57
+ leaf_map: state[:leaves],
58
+ topo_order: state[:evaluation_order],
59
+ decl_types: state[:inferred_types],
60
60
  state: state.to_h
61
61
  )
62
62
  end
63
63
 
64
64
  # Handle both old and new error formats for backward compatibility
65
- def format_errors(errors)
65
+ def self.format_errors(errors)
66
66
  return "" if errors.empty?
67
67
 
68
68
  errors.map(&:to_s).join("\n")