kumi 0.0.18 → 0.0.19
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/.rubocop.yml +4 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +25 -0
- data/CLAUDE.md +26 -139
- data/README.md +143 -372
- data/data/functions/agg/boolean.yaml +14 -0
- data/data/functions/agg/numeric.yaml +80 -0
- data/data/functions/agg/string.yaml +8 -0
- data/data/functions/core/arithmetic.yaml +50 -0
- data/data/functions/core/boolean.yaml +18 -0
- data/data/functions/core/comparison.yaml +42 -0
- data/data/functions/core/constructor.yaml +32 -0
- data/data/functions/core/select.yaml +7 -0
- data/data/functions/core/stencil.yaml +21 -0
- data/data/functions/core/string.yaml +19 -0
- data/data/kernels/javascript/agg/boolean.yaml +12 -0
- data/data/kernels/javascript/agg/numeric.yaml +27 -0
- data/data/kernels/javascript/agg/string.yaml +5 -0
- data/data/kernels/javascript/core/arithmetic.yaml +32 -0
- data/data/kernels/javascript/core/boolean.yaml +12 -0
- data/data/kernels/javascript/core/comparison.yaml +24 -0
- data/data/kernels/javascript/core/constructor.yaml +15 -0
- data/data/kernels/javascript/core/select.yaml +7 -0
- data/data/kernels/javascript/core/string.yaml +12 -0
- data/data/kernels/ruby/agg/boolean.yaml +18 -0
- data/data/kernels/ruby/agg/numeric.yaml +29 -0
- data/data/kernels/ruby/agg/string.yaml +5 -0
- data/data/kernels/ruby/core/arithmetic.yaml +38 -0
- data/data/kernels/ruby/core/boolean.yaml +15 -0
- data/data/kernels/ruby/core/comparison.yaml +30 -0
- data/data/kernels/ruby/core/constructor.yaml +17 -0
- data/data/kernels/ruby/core/select.yaml +4 -0
- data/data/kernels/ruby/core/string.yaml +15 -0
- data/debug_ordering.rb +52 -0
- data/docs/FORM_SCHEMA.md +85 -0
- data/docs/OUTPUT_SCHEMA.md +69 -0
- data/docs/SYNTAX.md +626 -373
- data/golden/array_element/expected/ast.txt +21 -0
- data/golden/array_element/expected/input_plan.txt +5 -0
- data/golden/array_element/expected/lir_00_unoptimized.txt +13 -0
- data/golden/array_element/expected/lir_01_hoist_scalar_references.txt +13 -0
- data/golden/array_element/expected/lir_02_inlined.txt +13 -0
- data/golden/array_element/expected/lir_03_cse.txt +13 -0
- data/golden/array_element/expected/lir_04_1_loop_fusion.txt +13 -0
- data/golden/array_element/expected/lir_04_loop_invcm.txt +13 -0
- data/golden/array_element/expected/lir_06_const_prop.txt +13 -0
- data/golden/array_element/expected/nast.txt +7 -0
- data/golden/array_element/expected/schema_javascript.mjs +13 -0
- data/golden/array_element/expected/schema_ruby.rb +41 -0
- data/golden/array_element/expected/snast.txt +7 -0
- data/golden/array_element/expected.json +5 -0
- data/golden/array_element/input.json +9 -0
- data/golden/array_element/schema.kumi +11 -0
- data/golden/array_index/expected/ast.txt +59 -0
- data/golden/array_index/expected/input_plan.txt +5 -0
- data/golden/array_index/expected/lir_00_unoptimized.txt +41 -0
- data/golden/array_index/expected/lir_01_hoist_scalar_references.txt +41 -0
- data/golden/array_index/expected/lir_02_inlined.txt +42 -0
- data/golden/array_index/expected/lir_03_cse.txt +40 -0
- data/golden/array_index/expected/lir_04_1_loop_fusion.txt +40 -0
- data/golden/array_index/expected/lir_04_loop_invcm.txt +40 -0
- data/golden/array_index/expected/lir_06_const_prop.txt +40 -0
- data/golden/array_index/expected/nast.txt +33 -0
- data/golden/array_index/expected/schema_javascript.mjs +46 -0
- data/golden/array_index/expected/schema_ruby.rb +75 -0
- data/golden/array_index/expected/snast.txt +33 -0
- data/golden/array_index/expected.json +5 -0
- data/golden/array_index/input.json +1 -0
- data/golden/array_index/schema.kumi +19 -0
- data/golden/array_operations/expected/ast.txt +50 -0
- data/golden/array_operations/expected/input_plan.txt +10 -0
- data/golden/array_operations/expected/lir_00_unoptimized.txt +47 -0
- data/golden/array_operations/expected/lir_01_hoist_scalar_references.txt +47 -0
- data/golden/array_operations/expected/lir_02_inlined.txt +47 -0
- data/golden/array_operations/expected/lir_03_cse.txt +47 -0
- data/golden/array_operations/expected/lir_04_1_loop_fusion.txt +47 -0
- data/golden/array_operations/expected/lir_04_loop_invcm.txt +47 -0
- data/golden/array_operations/expected/lir_06_const_prop.txt +47 -0
- data/golden/array_operations/expected/nast.txt +32 -0
- data/golden/array_operations/expected/schema_javascript.mjs +60 -0
- data/golden/array_operations/expected/schema_ruby.rb +91 -0
- data/golden/array_operations/expected/snast.txt +32 -0
- data/golden/array_operations/expected.json +27 -0
- data/golden/array_operations/input.json +8 -0
- data/golden/array_operations/schema.kumi +12 -10
- data/golden/cascade_logic/expected/ast.txt +37 -0
- data/golden/cascade_logic/expected/input_plan.txt +2 -0
- data/golden/cascade_logic/expected/lir_00_unoptimized.txt +29 -0
- data/golden/cascade_logic/expected/lir_01_hoist_scalar_references.txt +29 -0
- data/golden/cascade_logic/expected/lir_02_inlined.txt +37 -0
- data/golden/cascade_logic/expected/lir_03_cse.txt +30 -0
- data/golden/cascade_logic/expected/lir_04_1_loop_fusion.txt +30 -0
- data/golden/cascade_logic/expected/lir_04_loop_invcm.txt +30 -0
- data/golden/cascade_logic/expected/lir_06_const_prop.txt +30 -0
- data/golden/cascade_logic/expected/nast.txt +32 -0
- data/golden/cascade_logic/expected/schema_javascript.mjs +31 -0
- data/golden/cascade_logic/expected/schema_ruby.rb +57 -0
- data/golden/cascade_logic/expected/snast.txt +32 -0
- data/golden/cascade_logic/expected.json +5 -0
- data/golden/cascade_logic/input.json +4 -0
- data/golden/cascade_logic/schema.kumi +1 -3
- data/golden/chained_fusion/expected/ast.txt +57 -0
- data/golden/chained_fusion/expected/input_plan.txt +13 -0
- data/golden/chained_fusion/expected/lir_00_unoptimized.txt +76 -0
- data/golden/chained_fusion/expected/lir_01_hoist_scalar_references.txt +76 -0
- data/golden/chained_fusion/expected/lir_02_inlined.txt +114 -0
- data/golden/chained_fusion/expected/lir_03_cse.txt +97 -0
- data/golden/chained_fusion/expected/lir_04_1_loop_fusion.txt +99 -0
- data/golden/chained_fusion/expected/lir_04_loop_invcm.txt +97 -0
- data/golden/chained_fusion/expected/lir_06_const_prop.txt +97 -0
- data/golden/chained_fusion/expected/nast.txt +55 -0
- data/golden/chained_fusion/expected/schema_javascript.mjs +116 -0
- data/golden/chained_fusion/expected/schema_ruby.rb +149 -0
- data/golden/chained_fusion/expected/snast.txt +55 -0
- data/golden/chained_fusion/expected.json +45 -0
- data/golden/chained_fusion/input.json +51 -0
- data/golden/chained_fusion/schema.kumi +52 -0
- data/golden/element_arrays/expected/ast.txt +55 -0
- data/golden/element_arrays/expected/input_plan.txt +7 -0
- data/golden/element_arrays/expected/lir_00_unoptimized.txt +81 -0
- data/golden/element_arrays/expected/lir_01_hoist_scalar_references.txt +81 -0
- data/golden/element_arrays/expected/lir_02_inlined.txt +85 -0
- data/golden/element_arrays/expected/lir_03_cse.txt +83 -0
- data/golden/element_arrays/expected/lir_04_1_loop_fusion.txt +83 -0
- data/golden/element_arrays/expected/lir_04_loop_invcm.txt +83 -0
- data/golden/element_arrays/expected/lir_06_const_prop.txt +83 -0
- data/golden/element_arrays/expected/nast.txt +42 -0
- data/golden/element_arrays/expected/schema_javascript.mjs +106 -0
- data/golden/element_arrays/expected/schema_ruby.rb +141 -0
- data/golden/element_arrays/expected/snast.txt +42 -0
- data/golden/element_arrays/expected.json +55 -0
- data/golden/element_arrays/input.json +12 -0
- data/golden/element_arrays/schema.kumi +21 -0
- data/golden/empty_and_null_inputs/expected/ast.txt +42 -0
- data/golden/empty_and_null_inputs/expected/input_plan.txt +12 -0
- data/golden/empty_and_null_inputs/expected/lir_00_unoptimized.txt +31 -0
- data/golden/empty_and_null_inputs/expected/lir_01_hoist_scalar_references.txt +31 -0
- data/golden/empty_and_null_inputs/expected/lir_02_inlined.txt +51 -0
- data/golden/empty_and_null_inputs/expected/lir_03_cse.txt +49 -0
- data/golden/empty_and_null_inputs/expected/lir_04_1_loop_fusion.txt +49 -0
- data/golden/empty_and_null_inputs/expected/lir_04_loop_invcm.txt +49 -0
- data/golden/empty_and_null_inputs/expected/lir_06_const_prop.txt +49 -0
- data/golden/empty_and_null_inputs/expected/nast.txt +18 -0
- data/golden/empty_and_null_inputs/expected/schema_javascript.mjs +47 -0
- data/golden/empty_and_null_inputs/expected/schema_ruby.rb +79 -0
- data/golden/empty_and_null_inputs/expected/snast.txt +18 -0
- data/golden/empty_and_null_inputs/expected.json +8 -0
- data/golden/empty_and_null_inputs/input.json +16 -0
- data/golden/empty_and_null_inputs/schema.kumi +30 -0
- data/golden/game_of_life/expected/ast.txt +118 -0
- data/golden/game_of_life/expected/input_plan.txt +5 -0
- data/golden/game_of_life/expected/lir_00_unoptimized.txt +343 -0
- data/golden/game_of_life/expected/lir_01_hoist_scalar_references.txt +343 -0
- data/golden/game_of_life/expected/lir_02_inlined.txt +1918 -0
- data/golden/game_of_life/expected/lir_03_cse.txt +766 -0
- data/golden/game_of_life/expected/lir_04_1_loop_fusion.txt +766 -0
- data/golden/game_of_life/expected/lir_04_loop_invcm.txt +766 -0
- data/golden/game_of_life/expected/lir_06_const_prop.txt +766 -0
- data/golden/game_of_life/expected/nast.txt +104 -0
- data/golden/game_of_life/expected/schema_javascript.mjs +98 -0
- data/golden/game_of_life/expected/schema_ruby.rb +125 -0
- data/golden/game_of_life/expected/snast.txt +104 -0
- data/golden/game_of_life/expected.json +3 -0
- data/golden/game_of_life/input.json +8 -0
- data/golden/game_of_life/schema.kumi +33 -0
- data/golden/hash_keys/expected/ast.txt +29 -0
- data/golden/hash_keys/expected/input_plan.txt +2 -0
- data/golden/hash_keys/expected/lir_00_unoptimized.txt +18 -0
- data/golden/hash_keys/expected/lir_01_hoist_scalar_references.txt +18 -0
- data/golden/hash_keys/expected/lir_02_inlined.txt +18 -0
- data/golden/hash_keys/expected/lir_03_cse.txt +18 -0
- data/golden/hash_keys/expected/lir_04_1_loop_fusion.txt +18 -0
- data/golden/hash_keys/expected/lir_04_loop_invcm.txt +18 -0
- data/golden/hash_keys/expected/lir_06_const_prop.txt +18 -0
- data/golden/hash_keys/expected/nast.txt +46 -0
- data/golden/hash_keys/expected/schema_javascript.mjs +34 -0
- data/golden/hash_keys/expected/schema_ruby.rb +61 -0
- data/golden/hash_keys/expected/snast.txt +46 -0
- data/golden/hash_keys/expected.json +20 -0
- data/golden/hash_keys/input.json +4 -0
- data/golden/hash_keys/schema.kumi +14 -0
- data/golden/hash_value/expected/ast.txt +37 -0
- data/golden/hash_value/expected/input_plan.txt +7 -0
- data/golden/hash_value/expected/lir_00_unoptimized.txt +30 -0
- data/golden/hash_value/expected/lir_01_hoist_scalar_references.txt +30 -0
- data/golden/hash_value/expected/lir_02_inlined.txt +36 -0
- data/golden/hash_value/expected/lir_03_cse.txt +33 -0
- data/golden/hash_value/expected/lir_04_1_loop_fusion.txt +33 -0
- data/golden/hash_value/expected/lir_04_loop_invcm.txt +33 -0
- data/golden/hash_value/expected/lir_06_const_prop.txt +33 -0
- data/golden/hash_value/expected/nast.txt +25 -0
- data/golden/hash_value/expected/schema_javascript.mjs +46 -0
- data/golden/hash_value/expected/schema_ruby.rb +75 -0
- data/golden/hash_value/expected/snast.txt +25 -0
- data/golden/hash_value/expected.json +19 -0
- data/golden/hash_value/input.json +12 -0
- data/golden/hash_value/schema.kumi +19 -0
- data/golden/hierarchical_complex/expected/ast.txt +85 -0
- data/golden/hierarchical_complex/expected/input_plan.txt +23 -0
- data/golden/hierarchical_complex/expected/lir_00_unoptimized.txt +87 -0
- data/golden/hierarchical_complex/expected/lir_01_hoist_scalar_references.txt +87 -0
- data/golden/hierarchical_complex/expected/lir_02_inlined.txt +115 -0
- data/golden/hierarchical_complex/expected/lir_03_cse.txt +89 -0
- data/golden/hierarchical_complex/expected/lir_04_1_loop_fusion.txt +89 -0
- data/golden/hierarchical_complex/expected/lir_04_loop_invcm.txt +89 -0
- data/golden/hierarchical_complex/expected/lir_06_const_prop.txt +89 -0
- data/golden/hierarchical_complex/expected/nast.txt +49 -0
- data/golden/hierarchical_complex/expected/schema_javascript.mjs +121 -0
- data/golden/hierarchical_complex/expected/schema_ruby.rb +151 -0
- data/golden/hierarchical_complex/expected/snast.txt +49 -0
- data/golden/hierarchical_complex/expected.json +34 -0
- data/golden/hierarchical_complex/input.json +26 -0
- data/golden/hierarchical_complex/schema.kumi +38 -0
- data/golden/input_reference/expected/ast.txt +46 -0
- data/golden/input_reference/expected/input_plan.txt +15 -0
- data/golden/input_reference/expected/lir_00_unoptimized.txt +39 -0
- data/golden/input_reference/expected/lir_01_hoist_scalar_references.txt +39 -0
- data/golden/input_reference/expected/lir_02_inlined.txt +39 -0
- data/golden/input_reference/expected/lir_03_cse.txt +39 -0
- data/golden/input_reference/expected/lir_04_1_loop_fusion.txt +39 -0
- data/golden/input_reference/expected/lir_04_loop_invcm.txt +39 -0
- data/golden/input_reference/expected/lir_06_const_prop.txt +39 -0
- data/golden/input_reference/expected/nast.txt +21 -0
- data/golden/input_reference/expected/schema_javascript.mjs +45 -0
- data/golden/input_reference/expected/schema_ruby.rb +74 -0
- data/golden/input_reference/expected/snast.txt +21 -0
- data/golden/input_reference/expected.json +7 -0
- data/golden/input_reference/input.json +11 -0
- data/golden/input_reference/schema.kumi +22 -0
- data/golden/interleaved_fusion/expected/ast.txt +51 -0
- data/golden/interleaved_fusion/expected/input_plan.txt +13 -0
- data/golden/interleaved_fusion/expected/lir_00_unoptimized.txt +53 -0
- data/golden/interleaved_fusion/expected/lir_01_hoist_scalar_references.txt +53 -0
- data/golden/interleaved_fusion/expected/lir_02_inlined.txt +89 -0
- data/golden/interleaved_fusion/expected/lir_03_cse.txt +77 -0
- data/golden/interleaved_fusion/expected/lir_04_1_loop_fusion.txt +77 -0
- data/golden/interleaved_fusion/expected/lir_04_loop_invcm.txt +77 -0
- data/golden/interleaved_fusion/expected/lir_06_const_prop.txt +77 -0
- data/golden/interleaved_fusion/expected/nast.txt +41 -0
- data/golden/interleaved_fusion/expected/schema_javascript.mjs +86 -0
- data/golden/interleaved_fusion/expected/schema_ruby.rb +122 -0
- data/golden/interleaved_fusion/expected/snast.txt +41 -0
- data/golden/interleaved_fusion/expected.json +37 -0
- data/golden/interleaved_fusion/input.json +26 -0
- data/golden/interleaved_fusion/schema.kumi +57 -0
- data/golden/let_inline/expected/ast.txt +33 -0
- data/golden/let_inline/expected/input_plan.txt +2 -0
- data/golden/let_inline/expected/lir_00_unoptimized.txt +26 -0
- data/golden/let_inline/expected/lir_01_hoist_scalar_references.txt +26 -0
- data/golden/let_inline/expected/lir_02_inlined.txt +36 -0
- data/golden/let_inline/expected/lir_03_cse.txt +30 -0
- data/golden/let_inline/expected/lir_04_1_loop_fusion.txt +30 -0
- data/golden/let_inline/expected/lir_04_loop_invcm.txt +30 -0
- data/golden/let_inline/expected/lir_06_const_prop.txt +30 -0
- data/golden/let_inline/expected/nast.txt +26 -0
- data/golden/let_inline/expected/schema_javascript.mjs +11 -0
- data/golden/let_inline/expected/schema_ruby.rb +37 -0
- data/golden/let_inline/expected/snast.txt +26 -0
- data/golden/let_inline/expected.json +1 -0
- data/golden/let_inline/input.json +1 -0
- data/golden/let_inline/schema.kumi +11 -0
- data/golden/loop_fusion/expected/ast.txt +44 -0
- data/golden/loop_fusion/expected/input_plan.txt +13 -0
- data/golden/loop_fusion/expected/lir_00_unoptimized.txt +43 -0
- data/golden/loop_fusion/expected/lir_01_hoist_scalar_references.txt +43 -0
- data/golden/loop_fusion/expected/lir_02_inlined.txt +62 -0
- data/golden/loop_fusion/expected/lir_03_cse.txt +57 -0
- data/golden/loop_fusion/expected/lir_04_1_loop_fusion.txt +57 -0
- data/golden/loop_fusion/expected/lir_04_loop_invcm.txt +57 -0
- data/golden/loop_fusion/expected/lir_06_const_prop.txt +57 -0
- data/golden/loop_fusion/expected/nast.txt +32 -0
- data/golden/loop_fusion/expected/schema_javascript.mjs +64 -0
- data/golden/loop_fusion/expected/schema_ruby.rb +97 -0
- data/golden/loop_fusion/expected/snast.txt +32 -0
- data/golden/loop_fusion/expected.json +30 -0
- data/golden/loop_fusion/input.json +28 -0
- data/golden/loop_fusion/schema.kumi +32 -0
- data/golden/min_reduce_scope/expected/ast.txt +49 -0
- data/golden/min_reduce_scope/expected/input_plan.txt +9 -0
- data/golden/min_reduce_scope/expected/lir_00_unoptimized.txt +59 -0
- data/golden/min_reduce_scope/expected/lir_01_hoist_scalar_references.txt +59 -0
- data/golden/min_reduce_scope/expected/lir_02_inlined.txt +63 -0
- data/golden/min_reduce_scope/expected/lir_03_cse.txt +60 -0
- data/golden/min_reduce_scope/expected/lir_04_1_loop_fusion.txt +60 -0
- data/golden/min_reduce_scope/expected/lir_04_loop_invcm.txt +60 -0
- data/golden/min_reduce_scope/expected/lir_06_const_prop.txt +60 -0
- data/golden/min_reduce_scope/expected/nast.txt +29 -0
- data/golden/min_reduce_scope/expected/schema_javascript.mjs +66 -0
- data/golden/min_reduce_scope/expected/schema_ruby.rb +99 -0
- data/golden/min_reduce_scope/expected/snast.txt +29 -0
- data/golden/min_reduce_scope/expected.json +9 -0
- data/golden/min_reduce_scope/input.json +18 -0
- data/golden/min_reduce_scope/schema.kumi +25 -0
- data/golden/mixed_dimensions/expected/ast.txt +54 -0
- data/golden/mixed_dimensions/expected/input_plan.txt +15 -0
- data/golden/mixed_dimensions/expected/lir_00_unoptimized.txt +42 -0
- data/golden/mixed_dimensions/expected/lir_01_hoist_scalar_references.txt +42 -0
- data/golden/mixed_dimensions/expected/lir_02_inlined.txt +48 -0
- data/golden/mixed_dimensions/expected/lir_03_cse.txt +48 -0
- data/golden/mixed_dimensions/expected/lir_04_1_loop_fusion.txt +48 -0
- data/golden/mixed_dimensions/expected/lir_04_loop_invcm.txt +48 -0
- data/golden/mixed_dimensions/expected/lir_06_const_prop.txt +48 -0
- data/golden/mixed_dimensions/expected/nast.txt +22 -0
- data/golden/mixed_dimensions/expected/schema_javascript.mjs +53 -0
- data/golden/mixed_dimensions/expected/schema_ruby.rb +84 -0
- data/golden/mixed_dimensions/expected/snast.txt +22 -0
- data/golden/mixed_dimensions/expected.json +6 -0
- data/golden/mixed_dimensions/input.json +22 -0
- data/golden/mixed_dimensions/schema.kumi +35 -0
- data/golden/multirank_hoisting/expected/ast.txt +72 -0
- data/golden/multirank_hoisting/expected/input_plan.txt +18 -0
- data/golden/multirank_hoisting/expected/lir_00_unoptimized.txt +75 -0
- data/golden/multirank_hoisting/expected/lir_01_hoist_scalar_references.txt +75 -0
- data/golden/multirank_hoisting/expected/lir_02_inlined.txt +126 -0
- data/golden/multirank_hoisting/expected/lir_03_cse.txt +109 -0
- data/golden/multirank_hoisting/expected/lir_04_1_loop_fusion.txt +109 -0
- data/golden/multirank_hoisting/expected/lir_04_loop_invcm.txt +109 -0
- data/golden/multirank_hoisting/expected/lir_06_const_prop.txt +109 -0
- data/golden/multirank_hoisting/expected/nast.txt +39 -0
- data/golden/multirank_hoisting/expected/schema_javascript.mjs +128 -0
- data/golden/multirank_hoisting/expected/schema_ruby.rb +162 -0
- data/golden/multirank_hoisting/expected/snast.txt +39 -0
- data/golden/multirank_hoisting/expected.json +15 -0
- data/golden/multirank_hoisting/input.json +19 -0
- data/golden/multirank_hoisting/schema.kumi +38 -0
- data/golden/nested_hash/expected/ast.txt +22 -0
- data/golden/nested_hash/expected/input_plan.txt +5 -0
- data/golden/nested_hash/expected/lir_00_unoptimized.txt +10 -0
- data/golden/nested_hash/expected/lir_01_hoist_scalar_references.txt +10 -0
- data/golden/nested_hash/expected/lir_02_inlined.txt +10 -0
- data/golden/nested_hash/expected/lir_03_cse.txt +10 -0
- data/golden/nested_hash/expected/lir_04_1_loop_fusion.txt +10 -0
- data/golden/nested_hash/expected/lir_04_loop_invcm.txt +10 -0
- data/golden/nested_hash/expected/lir_06_const_prop.txt +10 -0
- data/golden/nested_hash/expected/nast.txt +8 -0
- data/golden/nested_hash/expected/schema_javascript.mjs +9 -0
- data/golden/nested_hash/expected/schema_ruby.rb +35 -0
- data/golden/nested_hash/expected/snast.txt +8 -0
- data/golden/nested_hash/expected.json +3 -0
- data/golden/nested_hash/input.json +7 -0
- data/golden/nested_hash/schema.kumi +11 -0
- data/golden/reduction_broadcast/expected/ast.txt +49 -0
- data/golden/reduction_broadcast/expected/input_plan.txt +13 -0
- data/golden/reduction_broadcast/expected/lir_00_unoptimized.txt +49 -0
- data/golden/reduction_broadcast/expected/lir_01_hoist_scalar_references.txt +49 -0
- data/golden/reduction_broadcast/expected/lir_02_inlined.txt +80 -0
- data/golden/reduction_broadcast/expected/lir_03_cse.txt +68 -0
- data/golden/reduction_broadcast/expected/lir_04_1_loop_fusion.txt +68 -0
- data/golden/reduction_broadcast/expected/lir_04_loop_invcm.txt +68 -0
- data/golden/reduction_broadcast/expected/lir_06_const_prop.txt +68 -0
- data/golden/reduction_broadcast/expected/nast.txt +24 -0
- data/golden/reduction_broadcast/expected/schema_javascript.mjs +74 -0
- data/golden/reduction_broadcast/expected/schema_ruby.rb +110 -0
- data/golden/reduction_broadcast/expected/snast.txt +24 -0
- data/golden/reduction_broadcast/expected.json +25 -0
- data/golden/reduction_broadcast/input.json +19 -0
- data/golden/reduction_broadcast/schema.kumi +34 -0
- data/golden/roll/expected/ast.txt +36 -0
- data/golden/roll/expected/input_plan.txt +3 -0
- data/golden/roll/expected/lir_00_unoptimized.txt +56 -0
- data/golden/roll/expected/lir_01_hoist_scalar_references.txt +56 -0
- data/golden/roll/expected/lir_02_inlined.txt +56 -0
- data/golden/roll/expected/lir_03_cse.txt +55 -0
- data/golden/roll/expected/lir_04_1_loop_fusion.txt +55 -0
- data/golden/roll/expected/lir_04_loop_invcm.txt +55 -0
- data/golden/roll/expected/lir_06_const_prop.txt +55 -0
- data/golden/roll/expected/nast.txt +26 -0
- data/golden/roll/expected/schema_javascript.mjs +65 -0
- data/golden/roll/expected/schema_ruby.rb +95 -0
- data/golden/roll/expected/snast.txt +26 -0
- data/golden/roll/expected.json +6 -0
- data/golden/roll/input.json +1 -0
- data/golden/roll/schema.kumi +13 -0
- data/golden/shift/expected/ast.txt +48 -0
- data/golden/shift/expected/input_plan.txt +3 -0
- data/golden/shift/expected/lir_00_unoptimized.txt +96 -0
- data/golden/shift/expected/lir_01_hoist_scalar_references.txt +96 -0
- data/golden/shift/expected/lir_02_inlined.txt +96 -0
- data/golden/shift/expected/lir_03_cse.txt +90 -0
- data/golden/shift/expected/lir_04_1_loop_fusion.txt +90 -0
- data/golden/shift/expected/lir_04_loop_invcm.txt +90 -0
- data/golden/shift/expected/lir_06_const_prop.txt +90 -0
- data/golden/shift/expected/nast.txt +38 -0
- data/golden/shift/expected/schema_javascript.mjs +106 -0
- data/golden/shift/expected/schema_ruby.rb +138 -0
- data/golden/shift/expected/snast.txt +38 -0
- data/golden/shift/expected.json +8 -0
- data/golden/shift/input.json +1 -0
- data/golden/shift/schema.kumi +15 -0
- data/golden/shift_2d/expected/ast.txt +88 -0
- data/golden/shift_2d/expected/input_plan.txt +5 -0
- data/golden/shift_2d/expected/lir_00_unoptimized.txt +274 -0
- data/golden/shift_2d/expected/lir_01_hoist_scalar_references.txt +274 -0
- data/golden/shift_2d/expected/lir_02_inlined.txt +274 -0
- data/golden/shift_2d/expected/lir_03_cse.txt +262 -0
- data/golden/shift_2d/expected/lir_04_1_loop_fusion.txt +262 -0
- data/golden/shift_2d/expected/lir_04_loop_invcm.txt +262 -0
- data/golden/shift_2d/expected/lir_06_const_prop.txt +262 -0
- data/golden/shift_2d/expected/nast.txt +74 -0
- data/golden/shift_2d/expected/schema_javascript.mjs +320 -0
- data/golden/shift_2d/expected/schema_ruby.rb +358 -0
- data/golden/shift_2d/expected/snast.txt +74 -0
- data/golden/shift_2d/expected.json +15 -0
- data/golden/shift_2d/input.json +14 -0
- data/golden/shift_2d/schema.kumi +25 -0
- data/golden/simple_math/expected/ast.txt +40 -0
- data/golden/simple_math/expected/input_plan.txt +2 -0
- data/golden/simple_math/expected/lir_00_unoptimized.txt +31 -0
- data/golden/simple_math/expected/lir_01_hoist_scalar_references.txt +31 -0
- data/golden/simple_math/expected/lir_02_inlined.txt +31 -0
- data/golden/simple_math/expected/lir_03_cse.txt +31 -0
- data/golden/simple_math/expected/lir_04_1_loop_fusion.txt +31 -0
- data/golden/simple_math/expected/lir_04_loop_invcm.txt +31 -0
- data/golden/simple_math/expected/lir_06_const_prop.txt +31 -0
- data/golden/simple_math/expected/nast.txt +33 -0
- data/golden/simple_math/expected/schema_javascript.mjs +33 -0
- data/golden/simple_math/expected/schema_ruby.rb +59 -0
- data/golden/simple_math/expected/snast.txt +33 -0
- data/golden/simple_math/expected.json +1 -0
- data/golden/simple_math/input.json +4 -0
- data/golden/simple_math/schema.kumi +2 -1
- data/golden/streaming_basics/expected/ast.txt +64 -0
- data/golden/streaming_basics/expected/input_plan.txt +8 -0
- data/golden/streaming_basics/expected/lir_00_unoptimized.txt +73 -0
- data/golden/streaming_basics/expected/lir_01_hoist_scalar_references.txt +73 -0
- data/golden/streaming_basics/expected/lir_02_inlined.txt +100 -0
- data/golden/streaming_basics/expected/lir_03_cse.txt +84 -0
- data/golden/streaming_basics/expected/lir_04_1_loop_fusion.txt +84 -0
- data/golden/streaming_basics/expected/lir_04_loop_invcm.txt +84 -0
- data/golden/streaming_basics/expected/lir_06_const_prop.txt +84 -0
- data/golden/streaming_basics/expected/nast.txt +48 -0
- data/golden/streaming_basics/expected/schema_javascript.mjs +94 -0
- data/golden/streaming_basics/expected/schema_ruby.rb +127 -0
- data/golden/streaming_basics/expected/snast.txt +48 -0
- data/golden/streaming_basics/expected.json +10 -0
- data/golden/streaming_basics/input.json +8 -0
- data/golden/streaming_basics/schema.kumi +24 -0
- data/golden/tuples/expected/ast.txt +48 -0
- data/golden/tuples/expected/input_plan.txt +1 -0
- data/golden/tuples/expected/lir_00_unoptimized.txt +40 -0
- data/golden/tuples/expected/lir_01_hoist_scalar_references.txt +40 -0
- data/golden/tuples/expected/lir_02_inlined.txt +48 -0
- data/golden/tuples/expected/lir_03_cse.txt +48 -0
- data/golden/tuples/expected/lir_04_1_loop_fusion.txt +48 -0
- data/golden/tuples/expected/lir_04_loop_invcm.txt +48 -0
- data/golden/tuples/expected/lir_06_const_prop.txt +48 -0
- data/golden/tuples/expected/nast.txt +42 -0
- data/golden/tuples/expected/schema_javascript.mjs +51 -0
- data/golden/tuples/expected/schema_ruby.rb +77 -0
- data/golden/tuples/expected/snast.txt +42 -0
- data/golden/tuples/expected.json +7 -0
- data/golden/tuples/input.json +3 -0
- data/golden/tuples/schema.kumi +11 -0
- data/golden/tuples_and_arrays/expected/ast.txt +44 -0
- data/golden/tuples_and_arrays/expected/input_plan.txt +7 -0
- data/golden/tuples_and_arrays/expected/lir_00_unoptimized.txt +41 -0
- data/golden/tuples_and_arrays/expected/lir_01_hoist_scalar_references.txt +41 -0
- data/golden/tuples_and_arrays/expected/lir_02_inlined.txt +62 -0
- data/golden/tuples_and_arrays/expected/lir_03_cse.txt +51 -0
- data/golden/tuples_and_arrays/expected/lir_04_1_loop_fusion.txt +51 -0
- data/golden/tuples_and_arrays/expected/lir_04_loop_invcm.txt +51 -0
- data/golden/tuples_and_arrays/expected/lir_06_const_prop.txt +51 -0
- data/golden/tuples_and_arrays/expected/nast.txt +28 -0
- data/golden/tuples_and_arrays/expected/schema_javascript.mjs +58 -0
- data/golden/tuples_and_arrays/expected/schema_ruby.rb +88 -0
- data/golden/tuples_and_arrays/expected/snast.txt +28 -0
- data/golden/tuples_and_arrays/expected.json +18 -0
- data/golden/tuples_and_arrays/input.json +7 -0
- data/golden/tuples_and_arrays/schema.kumi +38 -0
- data/golden/with_constants/expected/ast.txt +28 -0
- data/golden/with_constants/expected/input_plan.txt +2 -0
- data/golden/with_constants/expected/lir_00_unoptimized.txt +17 -0
- data/golden/with_constants/expected/lir_01_hoist_scalar_references.txt +17 -0
- data/golden/with_constants/expected/lir_02_inlined.txt +17 -0
- data/golden/with_constants/expected/lir_03_cse.txt +17 -0
- data/golden/with_constants/expected/lir_04_1_loop_fusion.txt +17 -0
- data/golden/with_constants/expected/lir_04_loop_invcm.txt +17 -0
- data/golden/with_constants/expected/lir_06_const_prop.txt +17 -0
- data/golden/with_constants/expected/nast.txt +21 -0
- data/golden/with_constants/expected/schema_javascript.mjs +18 -0
- data/golden/with_constants/expected/schema_ruby.rb +44 -0
- data/golden/with_constants/expected/snast.txt +15 -0
- data/golden/with_constants/schema.kumi +10 -0
- data/lib/kumi/analyzer.rb +76 -24
- data/lib/kumi/configuration.rb +60 -0
- data/lib/kumi/core/analyzer/binder.rb +121 -0
- data/lib/kumi/core/analyzer/checkpoint.rb +15 -9
- data/lib/kumi/core/analyzer/constant_evaluator.rb +32 -37
- data/lib/kumi/core/analyzer/constant_folding_helpers.rb +55 -0
- data/lib/kumi/core/analyzer/debug.rb +14 -16
- data/lib/kumi/core/analyzer/fn_aliases.rb +46 -0
- data/lib/kumi/core/analyzer/folder.rb +94 -0
- data/lib/kumi/core/analyzer/macro_expander.rb +69 -0
- data/lib/kumi/core/analyzer/passes/assemble_irv2_pass.rb +130 -0
- data/lib/kumi/core/analyzer/passes/attach_anchors_pass.rb +71 -0
- data/lib/kumi/core/analyzer/passes/attach_terminal_info_pass.rb +181 -0
- data/lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb +317 -0
- data/lib/kumi/core/analyzer/passes/codegen/js/emitter.rb +75 -0
- data/lib/kumi/core/analyzer/passes/codegen/js/output_buffer.rb +103 -0
- data/lib/kumi/core/analyzer/passes/codegen/js_pass.rb +27 -0
- data/lib/kumi/core/analyzer/passes/codegen/ruby/declaration_emitter.rb +321 -0
- data/lib/kumi/core/analyzer/passes/codegen/ruby/emitter.rb +85 -0
- data/lib/kumi/core/analyzer/passes/codegen/ruby/output_buffer.rb +111 -0
- data/lib/kumi/core/analyzer/passes/codegen/ruby_pass.rb +32 -0
- data/lib/kumi/core/analyzer/passes/constant_folding_pass.rb +33 -0
- data/lib/kumi/core/analyzer/passes/contract_checker_pass.rb +220 -0
- data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +5 -6
- data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +7 -3
- data/lib/kumi/core/analyzer/passes/input_collector.rb +74 -122
- data/lib/kumi/core/analyzer/passes/input_form_schema_pass.rb +43 -0
- data/lib/kumi/core/analyzer/passes/ir_dependency_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/ir_execution_schedule_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/join_reduce_planning_pass.rb +21 -23
- data/lib/kumi/core/analyzer/passes/lir/constant_propagation_pass.rb +84 -0
- data/lib/kumi/core/analyzer/passes/lir/dead_code_elimination_pass.rb +93 -0
- data/lib/kumi/core/analyzer/passes/lir/hoist_scalar_references_pass.rb +115 -0
- data/lib/kumi/core/analyzer/passes/lir/inline_declarations_pass.rb +274 -0
- data/lib/kumi/core/analyzer/passes/lir/instruction_scheduling_pass.rb +198 -0
- data/lib/kumi/core/analyzer/passes/lir/kernel_binding_pass.rb +30 -0
- data/lib/kumi/core/analyzer/passes/lir/local_cse_pass.rb +121 -0
- data/lib/kumi/core/analyzer/passes/lir/loop_fusion_pass.rb +156 -0
- data/lib/kumi/core/analyzer/passes/lir/loop_invariant_code_motion_pass.rb +148 -0
- data/lib/kumi/core/analyzer/passes/lir/lower_pass.rb +407 -0
- data/lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb +243 -0
- data/lib/kumi/core/analyzer/passes/lir/validation_pass.rb +83 -0
- data/lib/kumi/core/analyzer/passes/load_input_cse.rb +17 -16
- data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +4 -2
- data/lib/kumi/core/analyzer/passes/lower_to_irv2_pass.rb +197 -0
- data/lib/kumi/core/analyzer/passes/name_indexer.rb +4 -1
- data/lib/kumi/core/analyzer/passes/nast_dimensional_analyzer_pass.rb +237 -0
- data/lib/kumi/core/analyzer/passes/normalize_to_nast_pass.rb +156 -0
- data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +38 -0
- data/lib/kumi/core/analyzer/passes/pass_base.rb +30 -4
- data/lib/kumi/core/analyzer/passes/precompute_access_paths_pass.rb +93 -0
- data/lib/kumi/core/analyzer/passes/scope_resolution_pass.rb +33 -30
- data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +5 -26
- data/lib/kumi/core/analyzer/passes/snast_pass.rb +229 -0
- data/lib/kumi/core/analyzer/passes/toposorter.rb +1 -0
- data/lib/kumi/core/analyzer/passes/type_checker.rb +13 -0
- data/lib/kumi/core/analyzer/passes/type_inferencer_pass.rb +14 -16
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +2 -1
- data/lib/kumi/core/analyzer/plans.rb +12 -0
- data/lib/kumi/core/analyzer/state_serde.rb +4 -4
- data/lib/kumi/core/analyzer/structs/access_plan.rb +2 -2
- data/lib/kumi/core/analyzer/unsat_constant_evaluator.rb +59 -0
- data/lib/kumi/core/compiler/access_codegen.rb +1 -1
- data/lib/kumi/core/compiler/access_emit/base.rb +9 -5
- data/lib/kumi/core/compiler/access_emit/each_indexed.rb +10 -3
- data/lib/kumi/core/compiler/access_emit/materialize.rb +12 -5
- data/lib/kumi/core/compiler/access_emit/ravel.rb +10 -3
- data/lib/kumi/core/compiler/access_emit/read.rb +4 -1
- data/lib/kumi/core/compiler/access_planner.rb +42 -4
- data/lib/kumi/core/compiler/access_planner_v2.rb +164 -0
- data/lib/kumi/core/explain.rb +18 -11
- data/lib/kumi/core/functions/loader.rb +47 -0
- data/lib/kumi/core/functions/model.rb +10 -0
- data/lib/kumi/core/functions/type_rules.rb +108 -0
- data/lib/kumi/core/ir/execution_engine/interpreter.rb +1 -1
- data/lib/kumi/core/ir/execution_engine/profiler.rb +107 -97
- data/lib/kumi/core/ir.rb +6 -2
- data/lib/kumi/core/irv2/builder.rb +48 -0
- data/lib/kumi/core/irv2/declaration.rb +28 -0
- data/lib/kumi/core/irv2/module.rb +108 -0
- data/lib/kumi/core/irv2/value.rb +28 -0
- data/lib/kumi/core/lir/analyze.rb +64 -0
- data/lib/kumi/core/lir/build.rb +363 -0
- data/lib/kumi/core/lir/emit.rb +62 -0
- data/lib/kumi/core/lir/structs/instruction.rb +44 -0
- data/lib/kumi/core/lir/structs/literal.rb +14 -0
- data/lib/kumi/core/lir/structs/stamp.rb +13 -0
- data/lib/kumi/core/lir/support/error.rb +9 -0
- data/lib/kumi/core/lir/support/ids.rb +34 -0
- data/lib/kumi/core/lir/validate.rb +74 -0
- data/lib/kumi/core/lir.rb +34 -0
- data/lib/kumi/core/nast.rb +216 -0
- data/lib/kumi/core/ruby_parser/dsl.rb +2 -2
- data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +1 -1
- data/lib/kumi/core/ruby_parser/expression_converter.rb +10 -0
- data/lib/kumi/core/ruby_parser/input_builder.rb +16 -17
- data/lib/kumi/core/ruby_parser/schema_builder.rb +36 -10
- data/lib/kumi/core/ruby_parser/sugar.rb +64 -0
- data/lib/kumi/core/types/builder.rb +2 -2
- data/lib/kumi/core/types/normalizer.rb +2 -0
- data/lib/kumi/core/types/validator.rb +10 -3
- data/lib/kumi/core/types.rb +7 -0
- data/lib/kumi/dev/codegen.rb +194 -0
- data/lib/kumi/dev/golden/generator.rb +105 -0
- data/lib/kumi/dev/golden/reporter.rb +160 -0
- data/lib/kumi/dev/golden/representation.rb +45 -0
- data/lib/kumi/dev/golden/result.rb +98 -0
- data/lib/kumi/dev/golden/runtime_test.rb +93 -0
- data/lib/kumi/dev/golden/suite.rb +131 -0
- data/lib/kumi/dev/golden/verifier.rb +76 -0
- data/lib/kumi/dev/golden.rb +75 -0
- data/lib/kumi/dev/ir.rb +4 -4
- data/lib/kumi/dev/parse.rb +1 -1
- data/lib/kumi/dev/pretty_printer.rb +229 -0
- data/lib/kumi/dev/printer/irv2_formatter.rb +163 -0
- data/lib/kumi/dev/printer/width_aware_json.rb +44 -0
- data/lib/kumi/dev/profile_aggregator.rb +36 -38
- data/lib/kumi/dev/profile_runner.rb +19 -23
- data/lib/kumi/dev/runner.rb +12 -22
- data/lib/kumi/dev/support/kumi_runner.mjs +39 -0
- data/lib/kumi/dev.rb +3 -3
- data/lib/kumi/frontends/ruby.rb +12 -12
- data/lib/kumi/frontends/text.rb +26 -21
- data/lib/kumi/frontends.rb +6 -8
- data/lib/kumi/kernel_registry.rb +59 -0
- data/lib/kumi/pack/builder.rb +229 -0
- data/lib/kumi/pack.rb +15 -0
- data/lib/kumi/registry_v2/loader.rb +81 -0
- data/lib/kumi/registry_v2.rb +118 -0
- data/lib/kumi/schema.rb +83 -43
- data/lib/kumi/support/diff.rb +3 -2
- data/lib/kumi/support/ir_render.rb +1 -1
- data/lib/kumi/support/lir_printer.rb +143 -0
- data/lib/kumi/support/nast_printer.rb +93 -0
- data/lib/kumi/support/s_expression_printer.rb +5 -4
- data/lib/kumi/support/snast_printer.rb +111 -0
- data/lib/kumi/syntax/call_expression.rb +1 -1
- data/lib/kumi/syntax/input_declaration.rb +2 -2
- data/lib/kumi/syntax/node.rb +4 -12
- data/lib/kumi/syntax/root.rb +10 -0
- data/lib/kumi/syntax/trait_declaration.rb +1 -0
- data/lib/kumi/syntax/value_declaration.rb +1 -0
- data/lib/kumi/version.rb +1 -1
- data/lib/kumi.rb +47 -5
- metadata +571 -54
- data/docs/AST.md +0 -133
- data/docs/DSL.md +0 -154
- data/docs/FUNCTIONS.md +0 -176
- data/docs/VECTOR_SEMANTICS.md +0 -286
- data/docs/compiler_design_principles.md +0 -86
- data/docs/dev/analyzer-debug.md +0 -52
- data/docs/dev/parse-command.md +0 -64
- data/docs/dev/vm-profiling.md +0 -95
- data/docs/development/README.md +0 -120
- data/docs/development/error-reporting.md +0 -361
- data/docs/features/README.md +0 -58
- data/docs/features/analysis-type-inference.md +0 -42
- data/docs/features/analysis-unsat-detection.md +0 -71
- data/docs/features/hierarchical-broadcasting.md +0 -415
- data/docs/features/input-declaration-system.md +0 -58
- data/docs/features/performance.md +0 -14
- data/docs/features/s-expression-printer.md +0 -77
- data/docs/schema_metadata/broadcasts.md +0 -53
- data/docs/schema_metadata/cascades.md +0 -45
- data/docs/schema_metadata/declarations.md +0 -54
- data/docs/schema_metadata/dependencies.md +0 -57
- data/docs/schema_metadata/evaluation_order.md +0 -29
- data/docs/schema_metadata/examples.md +0 -95
- data/docs/schema_metadata/inferred_types.md +0 -46
- data/docs/schema_metadata/inputs.md +0 -86
- data/docs/schema_metadata.md +0 -108
- data/golden/mixed_nesting/schema.kumi +0 -42
- data/lib/kumi/core/function_registry/collection_functions.rb +0 -298
- data/lib/kumi/core/function_registry/comparison_functions.rb +0 -33
- data/lib/kumi/core/function_registry/conditional_functions.rb +0 -48
- data/lib/kumi/core/function_registry/function_builder.rb +0 -184
- data/lib/kumi/core/function_registry/logical_functions.rb +0 -214
- data/lib/kumi/core/function_registry/math_functions.rb +0 -74
- data/lib/kumi/core/function_registry/stat_functions.rb +0 -156
- data/lib/kumi/core/function_registry/string_functions.rb +0 -57
- data/lib/kumi/core/function_registry/type_functions.rb +0 -53
- data/lib/kumi/core/function_registry.rb +0 -176
- data/lib/kumi/registry.rb +0 -32
- data/lib/kumi/runtime/executable.rb +0 -135
- data/lib/kumi/runtime/run.rb +0 -105
- data/performance_results.txt +0 -63
- data/scripts/analyze_broadcast_methods.rb +0 -68
- data/scripts/analyze_cascade_methods.rb +0 -74
- data/scripts/check_broadcasting_coverage.rb +0 -51
- data/scripts/find_dead_code.rb +0 -114
- data/scripts/generate_function_docs.rb +0 -71
- data/scripts/test_mixed_nesting_performance.rb +0 -206
data/README.md
CHANGED
@@ -1,436 +1,207 @@
|
|
1
|
-
# Kumi
|
1
|
+
# Kumi
|
2
2
|
|
3
3
|
[](https://github.com/amuta/kumi/actions)
|
4
4
|
[](https://badge.fury.io/rb/kumi)
|
5
5
|
|
6
|
-
**Kumi** is a declarative rules-and-calculation DSL for Ruby. It compiles business logic into a **typed, analyzable dependency graph** with **vector semantics** over nested data, performs **static checks** at definition time, **lowers to a compact IR**, and executes **deterministically**.
|
7
6
|
|
8
|
-
|
7
|
+
---
|
9
8
|
|
9
|
+
**Status**: experimental. Public API may change. Typing and some static checks are still evolving.
|
10
10
|
|
11
|
-
|
11
|
+
**Feedback**: have a use case or a paper cut? Open an issue or reach out.
|
12
12
|
|
13
|
-
|
13
|
+
---
|
14
14
|
|
15
|
-
```ruby
|
16
|
-
module FederalTax2024
|
17
|
-
extend Kumi::Schema
|
18
|
-
|
19
|
-
schema do
|
20
|
-
input do
|
21
|
-
float :income
|
22
|
-
string :filing_status, domain: %w[single married_joint]
|
23
|
-
end
|
24
|
-
|
25
|
-
# Standard deduction by filing status
|
26
|
-
trait :single, input.filing_status == "single"
|
27
|
-
trait :married, input.filing_status == "married_joint"
|
28
|
-
|
29
|
-
value :std_deduction do
|
30
|
-
on single, 14_600
|
31
|
-
on married, 29_200
|
32
|
-
base 21_900 # head_of_household
|
33
|
-
end
|
34
|
-
|
35
|
-
value :taxable_income, fn(:max, [input.income - std_deduction, 0])
|
36
|
-
|
37
|
-
# Federal tax brackets
|
38
|
-
value :fed_breaks do
|
39
|
-
on single, [11_600, 47_150, 100_525, 191_950, 243_725, 609_350, Float::INFINITY]
|
40
|
-
on married, [23_200, 94_300, 201_050, 383_900, 487_450, 731_200, Float::INFINITY]
|
41
|
-
end
|
42
|
-
|
43
|
-
value :fed_rates, [0.10, 0.12, 0.22, 0.24, 0.32, 0.35, 0.37]
|
44
|
-
value :fed_calc, fn(:piecewise_sum, taxable_income, fed_breaks, fed_rates)
|
45
|
-
value :fed_tax, fed_calc[0]
|
46
|
-
|
47
|
-
# FICA taxes
|
48
|
-
value :ss_tax, fn(:min, [input.income, 168_600]) * 0.062
|
49
|
-
value :medicare_tax, input.income * 0.0145
|
50
|
-
|
51
|
-
value :total_tax, fed_tax + ss_tax + medicare_tax
|
52
|
-
value :after_tax, input.income - total_tax
|
53
|
-
end
|
54
|
-
end
|
55
15
|
|
56
|
-
|
57
|
-
result = FederalTax2024.from(income: 100_000, filing_status: "single")
|
58
|
-
result[:total_tax] # => 21,491.00
|
59
|
-
result[:after_tax] # => 78,509.00
|
60
|
-
```
|
16
|
+
Kumi is a **declarative calculation DSL for Ruby**. You write business rules once; Kumi:
|
61
17
|
|
62
|
-
|
18
|
+
- Builds a **typed dependency graph** with vector semantics.
|
19
|
+
- Performs **static validation** at definition time.
|
20
|
+
- Lowers to a **portable Low-level IR (LIR)**.
|
21
|
+
- Code-generates standalone **Ruby** and **JavaScript**.
|
63
22
|
|
64
|
-
|
23
|
+
Targets: finance, tax, pricing, insurance, payroll, analytics—domains where **correctness, transparency, and reproducibility** matter.
|
65
24
|
|
66
|
-
|
25
|
+
---
|
67
26
|
|
68
|
-
|
69
|
-
# Requires Ruby 3.1+
|
70
|
-
# No external dependencies
|
71
|
-
gem install kumi
|
72
|
-
```
|
73
|
-
|
74
|
-
## Core Features
|
75
|
-
|
76
|
-
<details>
|
77
|
-
<summary><strong>Schema Primitives</strong> - Four building blocks for business logic</summary>
|
78
|
-
|
79
|
-
### Schema Primitives
|
80
|
-
|
81
|
-
Kumi schemas are built from four primitives:
|
82
|
-
|
83
|
-
**Inputs** define the data flowing into your schema with built-in validation:
|
84
|
-
```ruby
|
85
|
-
input do
|
86
|
-
float :price, domain: 0..1000.0 # Validates range
|
87
|
-
integer :quantity, domain: 1..10000 # Validates range
|
88
|
-
string :tier, domain: %w[standard premium] # Validates inclusion
|
89
|
-
end
|
90
|
-
```
|
91
|
-
|
92
|
-
**Values** are computed attributes that automatically memoize their results
|
93
|
-
```ruby
|
94
|
-
value :subtotal, input.price * input.quantity
|
95
|
-
value :tax_rate, 0.08
|
96
|
-
value :tax_amount, subtotal * tax_rate
|
97
|
-
```
|
27
|
+
## Codegen: Currently Ruby and JavaScript
|
98
28
|
|
99
|
-
|
100
|
-
```ruby
|
101
|
-
trait :bulk_order, input.quantity >= 100
|
102
|
-
trait :premium_customer, input.tier == "premium"
|
103
|
-
|
104
|
-
value :discount do
|
105
|
-
on bulk_order, premium_customer, 0.25 # 25% for bulk premium orders
|
106
|
-
on bulk_order, 0.15 # 15% for bulk orders
|
107
|
-
on premium_customer, 0.10 # 10% for premium customers
|
108
|
-
base 0.0 # No discount otherwise
|
109
|
-
end
|
110
|
-
```
|
29
|
+
*Note: this is not available on the last published gem version (0.0.18), but if you clone this repository you can just copy a ./golden/$schema_name and modify schema.kumi as you and run bin/kumi golden test $schema_name*
|
111
30
|
|
112
|
-
**Functions** are computational building blocks:
|
113
31
|
|
114
|
-
|
115
|
-
value :final_price, [subtotal - discount_amount, 0].max
|
116
|
-
value :monthly_payment, fn(:pmt, rate: 0.05/12, nper: 36, pv: -loan_amount)
|
117
|
-
```
|
118
|
-
Note: You can find a list all core functions in [docs/FUNCTIONS.md](docs/FUNCTIONS.md)
|
32
|
+
Kumi emits the kernel for your schema with no runtime in the target language. You can use it within your ruby application backend and/or export to the client.
|
119
33
|
|
120
|
-
</details>
|
121
34
|
|
122
35
|
<details>
|
123
|
-
<summary><strong>
|
124
|
-
|
125
|
-
### Analysis & Introspection
|
126
|
-
|
127
|
-
Kumi provides comprehensive analysis capabilities - catching errors at definition time and exposing schema structure for tooling and debugging.
|
128
|
-
|
129
|
-
#### **Static Analysis: Catch Errors Early**
|
130
|
-
|
131
|
-
Kumi catches many types of business logic errors that cause runtime failures or silent bugs:
|
36
|
+
<summary><strong>Schema</strong></summary>
|
132
37
|
|
133
38
|
```ruby
|
134
|
-
module
|
39
|
+
module GameOfLife
|
135
40
|
extend Kumi::Schema
|
136
|
-
|
41
|
+
|
137
42
|
schema do
|
138
43
|
input do
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
end
|
145
|
-
|
146
|
-
# Risk assessment with subtle interdependencies
|
147
|
-
trait :young_driver, input.age < 25
|
148
|
-
trait :experienced, input.years_experience >= 5
|
149
|
-
trait :high_risk, input.risk_category == "high"
|
150
|
-
trait :senior_driver, input.age >= 65
|
151
|
-
|
152
|
-
# Base premium calculation
|
153
|
-
value :base_premium, input.coverage_amount * 0.02
|
154
|
-
|
155
|
-
# Experience adjustment with subtle circular reference
|
156
|
-
value :experience_factor do
|
157
|
-
on experienced & young_driver, experience_discount * 0.8 # ❌ Uses experience_discount before it's defined
|
158
|
-
on experienced, 0.85
|
159
|
-
on young_driver, 1.25
|
160
|
-
base 1.0
|
161
|
-
end
|
162
|
-
|
163
|
-
# Risk multipliers that create impossible combinations
|
164
|
-
value :risk_multiplier do
|
165
|
-
on high_risk & experienced, 1.5 # High risk but experienced
|
166
|
-
on high_risk, 2.0 # Just high risk
|
167
|
-
on low_risk & young_driver, 0.9 # ❌ low_risk is undefined (typo for input.risk_category)
|
168
|
-
base 1.0
|
169
|
-
end
|
170
|
-
|
171
|
-
# Claims history impact
|
172
|
-
trait :claims_free, fn(:not, input.has_claims)
|
173
|
-
trait :perfect_record, claims_free & experienced & fn(:not, young_driver)
|
174
|
-
|
175
|
-
# Discount calculation with type error
|
176
|
-
value :experience_discount do
|
177
|
-
on perfect_record, input.years_experience + "%" # ❌ String concatenation with integer
|
178
|
-
on claims_free, 0.95
|
179
|
-
base 1.0
|
180
|
-
end
|
181
|
-
|
182
|
-
# Premium calculation chain
|
183
|
-
value :adjusted_premium, base_premium * experience_factor * risk_multiplier
|
184
|
-
|
185
|
-
# Age-based impossible logic
|
186
|
-
trait :mature_professional, senior_driver & experienced & young_driver # ❌ Can't be senior AND young
|
187
|
-
|
188
|
-
# Final premium with self-referencing cascade
|
189
|
-
value :final_premium do
|
190
|
-
on mature_professional, adjusted_premium * 0.8
|
191
|
-
on senior_driver, adjusted_premium * senior_adjustment # ❌ senior_adjustment undefined
|
192
|
-
base final_premium * 1.1 # ❌ Self-reference in base case
|
44
|
+
array :rows do
|
45
|
+
array :col do
|
46
|
+
integer :alive # 0 or 1
|
47
|
+
end
|
48
|
+
end
|
193
49
|
end
|
194
|
-
|
195
|
-
# Monthly payment calculation with function arity error
|
196
|
-
value :monthly_payment, fn(:divide, final_premium) # ❌ divide needs 2 arguments, got 1
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
# Static analysis catches these errors:
|
201
|
-
# ❌ Circular reference: experience_factor → experience_discount → experience_factor
|
202
|
-
# ❌ Undefined reference: low_risk (should be input.risk_category == "low")
|
203
|
-
# ❌ Type mismatch: integer + string in experience_discount
|
204
|
-
# ❌ Impossible conjunction: senior_driver & young_driver
|
205
|
-
# ❌ Undefined reference: senior_adjustment
|
206
|
-
# ❌ Self-reference cycle: final_premium references itself in base case
|
207
|
-
# ❌ Function arity error: divide expects 2 arguments, got 1
|
208
|
-
```
|
209
|
-
|
210
|
-
#### **Runtime Introspection: Debug and Understand**
|
211
|
-
|
212
|
-
**Explainability**: Trace exactly how any value is computed, step-by-step. This is invaluable for debugging complex logic and auditing results.
|
213
50
|
|
214
|
-
|
215
|
-
Kumi::Explain.call(FederalTax2024, :fed_tax, inputs: {income: 100_000, filing_status: "single"})
|
216
|
-
# => fed_tax = fed_calc[0]
|
217
|
-
# = (fed_calc = piecewise_sum(taxable_income, fed_breaks, fed_rates)
|
218
|
-
# = piecewise_sum(85_400, [11_600, 47_150, ...], [0.10, 0.12, ...])
|
219
|
-
# = [15_099.50, 0.22])
|
220
|
-
# = 15_099.50
|
221
|
-
```
|
51
|
+
let :a, input.rows.col.alive
|
222
52
|
|
223
|
-
|
53
|
+
# axis_offset: 0 = x, 1 = y
|
54
|
+
let :n, shift(a, -1, axis_offset: 1)
|
55
|
+
let :s, shift(a, 1, axis_offset: 1)
|
56
|
+
let :w, shift(a, -1)
|
57
|
+
let :e, shift(a, 1)
|
58
|
+
let :nw, shift(n, -1)
|
59
|
+
let :ne, shift(n, 1)
|
60
|
+
let :sw, shift(s, -1)
|
61
|
+
let :se, shift(s, 1)
|
224
62
|
|
225
|
-
|
63
|
+
let :neighbors, fn(:sum, [n, s, w, e, nw, ne, sw, se])
|
226
64
|
|
227
|
-
|
228
|
-
|
65
|
+
# Conway rules
|
66
|
+
let :alive, a > 0
|
67
|
+
let :n3_alive, neighbors == 3
|
68
|
+
let :n2_alive, neighbors == 2
|
69
|
+
let :keep_alive, n2_alive & alive
|
229
70
|
|
230
|
-
|
231
|
-
metadata.inputs # => { name: { type: :string, domain: ... } }
|
232
|
-
metadata.values # => { name: { dependencies: [...], expression: "..." } }
|
233
|
-
metadata.traits # => { name: { condition: "...", dependencies: [...] } }
|
71
|
+
let :next_alive, n3_alive | keep_alive
|
234
72
|
|
235
|
-
|
236
|
-
|
237
|
-
metadata.evaluation_order # Topologically sorted computation order
|
73
|
+
value :next_state, select(next_alive, 1, 0)
|
74
|
+
end
|
238
75
|
|
239
|
-
|
240
|
-
|
241
|
-
metadata.to_json_schema # => JSON Schema for input validation
|
242
|
-
```
|
76
|
+
end
|
77
|
+
````
|
243
78
|
|
244
|
-
|
79
|
+
</details>
|
245
80
|
|
246
|
-
|
81
|
+
<details>
|
82
|
+
<summary><strong>Optimized LIR (lowered IR)</strong></summary>
|
247
83
|
|
248
|
-
```
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
84
|
+
```bash
|
85
|
+
# ...
|
86
|
+
(Declaration next_state
|
87
|
+
%t285 = load_input "rows" :: array
|
88
|
+
%t1539 = Length %t285 :: integer
|
89
|
+
%t1540 = const -1 :: integer
|
90
|
+
%t1542 = const 0 :: integer
|
91
|
+
%t1546 = const 1 :: integer
|
92
|
+
%t1334 = const 3 :: integer
|
93
|
+
%t1339 = const 2 :: integer
|
94
|
+
%t1547 = call core.sub(%t1539, %t1546) :: integer
|
95
|
+
loop rows id=L31 in %t285 as el=%rows_el_286, idx=%rows_i_287
|
96
|
+
%t1541 = call core.sub(%rows_i_287, %t1540) :: integer
|
97
|
+
%t1561 = call core.sub(%rows_i_287, %t1546) :: integer
|
98
|
+
%t1580 = call core.mod(%rows_i_287, %t1539) :: integer
|
99
|
+
# ...
|
257
100
|
```
|
258
101
|
|
259
102
|
</details>
|
260
103
|
|
261
104
|
<details>
|
262
|
-
<summary><strong>
|
105
|
+
<summary><strong>Generated Ruby (excerpt)</strong></summary>
|
263
106
|
|
264
|
-
### Hierarchical Broadcasting
|
265
|
-
|
266
|
-
Kumi broadcasts operations over hierarchical data structures with two complementary access modes for maximum flexibility.
|
267
|
-
|
268
|
-
See [docs/features/hierarchical-broadcasting.md](docs/features/hierarchical-broadcasting.md) for detailed documentation.
|
269
|
-
|
270
|
-
**Business Scenario**: E-commerce checkout with dynamic pricing rules
|
271
|
-
|
272
|
-
> **"As an e-commerce platform, I need to calculate order totals with complex discount rules:**
|
273
|
-
> - Premium members get 15% off electronics
|
274
|
-
> - Bulk orders (5+ items) get 10% off that item
|
275
|
-
> - Free shipping on orders over $100
|
276
|
-
> - Calculate: item subtotals, total discounts, shipping, final total
|
277
|
-
>
|
278
|
-
> **The challenge:** Each order has different items, quantities, categories, and customer tiers. The discount logic involves multiple conditions - some items qualify for multiple discounts, others for none. Traditional pricing code requires nested if-statements and manual calculations."
|
279
|
-
|
280
|
-
**Kumi Solution** (16 lines of declarative pricing logic):
|
281
107
|
```ruby
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
integer :quantity
|
290
|
-
string :category
|
291
|
-
end
|
292
|
-
string :customer_tier
|
293
|
-
float :shipping_threshold
|
294
|
-
end
|
295
|
-
|
296
|
-
# Calculate item subtotals and discount eligibility
|
297
|
-
value :subtotals, input.items.price * input.items.quantity
|
298
|
-
trait :electronics, input.items.category == "electronics"
|
299
|
-
trait :bulk_item, input.items.quantity >= 5
|
300
|
-
trait :premium_customer, input.customer_tier == "premium"
|
301
|
-
|
302
|
-
# Apply layered discounts (premium + bulk can stack)
|
303
|
-
trait :premium_electronics, premium_customer & electronics
|
304
|
-
trait :stacked_discount, premium_electronics & bulk_item
|
305
|
-
|
306
|
-
value :discounted_prices do
|
307
|
-
on stacked_discount, input.items.price * 0.75 # 15% + 10% = 25% off
|
308
|
-
on premium_electronics, input.items.price * 0.85 # 15% off
|
309
|
-
on bulk_item, input.items.price * 0.90 # 10% off
|
310
|
-
base input.items.price # No discount
|
311
|
-
end
|
312
|
-
|
313
|
-
value :final_subtotals, discounted_prices * input.items.quantity
|
314
|
-
|
315
|
-
# Order totals and conditional shipping
|
316
|
-
value :subtotal, fn(:sum, final_subtotals)
|
317
|
-
value :total_savings, fn(:sum, subtotals) - subtotal
|
318
|
-
value :shipping, subtotal > input.shipping_threshold ? 0.0 : 9.99
|
319
|
-
value :total, subtotal + shipping
|
108
|
+
# Autogenerated by Kumi Codegen
|
109
|
+
module Kumi::Compiled::KUMI_bd17a3ebee1bec4e58b72118d43e8c1c93bf773f257fc93d9c32a783d212ea4f
|
110
|
+
def self.from(input_data = nil)
|
111
|
+
instance = Object.new
|
112
|
+
instance.extend(self)
|
113
|
+
instance.instance_variable_set(:@input, input_data)
|
114
|
+
instance
|
320
115
|
end
|
321
|
-
end
|
322
|
-
```
|
323
|
-
|
324
|
-
**Mixed Access Modes**: Both object and element access can be used together in the same schema:
|
325
116
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
input do
|
332
|
-
# Object access mode - structured business data
|
333
|
-
array :users do
|
334
|
-
string :name
|
335
|
-
integer :age
|
336
|
-
end
|
337
|
-
|
338
|
-
# Element access mode - multi-dimensional raw arrays
|
339
|
-
array :recent_purchases do
|
340
|
-
element :integer, :days_ago
|
341
|
-
end
|
342
|
-
end
|
117
|
+
def self.__kumi_executable__
|
118
|
+
instance = Object.new
|
119
|
+
instance.extend(self)
|
120
|
+
instance
|
121
|
+
end
|
343
122
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
# Element access handles nested arrays with progressive path traversal
|
349
|
-
value :all_purchase_days, fn(:flatten, input.recent_purchases.days_ago)
|
350
|
-
value :recent_flags, input.recent_purchases.days_ago < 5
|
351
|
-
trait :has_recent_purchase, fn(:any?, fn(:flatten, recent_flags))
|
352
|
-
|
353
|
-
# Progressive dimensional analysis - each path level goes deeper
|
354
|
-
value :purchase_dimensions, [
|
355
|
-
fn(:size, input.recent_purchases), # Number of purchase groups
|
356
|
-
fn(:size, input.recent_purchases.days_ago) # Total individual purchase days
|
357
|
-
]
|
358
|
-
|
359
|
-
# Mixed usage in conditions
|
360
|
-
trait :adult_users, input.users.age >= 18
|
361
|
-
value :adult_count, fn(:count_if, adult_users)
|
123
|
+
def update(input_data)
|
124
|
+
@input = @input.merge(input_data)
|
125
|
+
self
|
362
126
|
end
|
363
|
-
end
|
364
127
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
128
|
+
def [](name)
|
129
|
+
case name
|
130
|
+
when :next_state then _next_state
|
131
|
+
else raise KeyError, "Unknown declaration"
|
132
|
+
end
|
133
|
+
end
|
370
134
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
135
|
+
def _next_state(input = @input)
|
136
|
+
out = []
|
137
|
+
t285 = input["rows"] || input[:rows]
|
138
|
+
t1539 = t285.length
|
139
|
+
t1540 = -1
|
140
|
+
t1542 = 0
|
141
|
+
t1546 = 1
|
142
|
+
t1334 = 3
|
143
|
+
t1339 = 2
|
144
|
+
t1547 = t1539 - t1546
|
145
|
+
t285.each_with_index do |rows_el_286, rows_i_287|
|
146
|
+
out_1 = []
|
147
|
+
t1541 = rows_i_287 - t1540
|
148
|
+
t1561 = rows_i_287 - t1546
|
149
|
+
t1580 = rows_i_287 % t1539
|
150
|
+
t1543 = t1541 >= t1542
|
151
|
+
t1544 = t1541 < t1539
|
152
|
+
t1549 = [[ t1541, t1542 ].max, t1547 ].min
|
153
|
+
t1563 = t1561 >= t1542
|
154
|
+
# ...
|
375
155
|
```
|
376
156
|
|
377
157
|
</details>
|
378
158
|
|
379
159
|
<details>
|
380
|
-
<summary><strong>
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
160
|
+
<summary><strong>Generated JavaScript (excerpt)</strong></summary>
|
161
|
+
|
162
|
+
```js
|
163
|
+
export class KumiCompiledModule {
|
164
|
+
_next_state(input) {
|
165
|
+
let out = [];
|
166
|
+
let t285 = input["rows"];
|
167
|
+
let t1539 = t285.length
|
168
|
+
const t1540 = -1;
|
169
|
+
const t1542 = 0;
|
170
|
+
const t1546 = 1;
|
171
|
+
const t1334 = 3;
|
172
|
+
const t1339 = 2;
|
173
|
+
let t1547 = t1539 - t1546;
|
174
|
+
t285.forEach((rows_el_286, rows_i_287) => {
|
175
|
+
let out_1 = [];
|
176
|
+
let t1541 = rows_i_287 - t1540;
|
177
|
+
let t1561 = rows_i_287 - t1546;
|
178
|
+
let t1580 = ((rows_i_287 % t1539) + t1539) % t1539;
|
179
|
+
let t1543 = t1541 >= t1542;
|
180
|
+
let t1544 = t1541 < t1539;
|
181
|
+
let t1549 = Math.min(Math.max(t1541, t1542), t1547);
|
182
|
+
let t1563 = t1561 >= t1542;
|
183
|
+
let t1564 = t1561 < t1539;
|
184
|
+
let t1569 = Math.min(Math.max(t1561, t1542), t1547);
|
185
|
+
let t1581 = t1580 + t1539;
|
186
|
+
let t1545 = t1543 && t1544;
|
187
|
+
let t1550 = t285[t1549]
|
188
|
+
// ...
|
395
189
|
```
|
396
|
-
</details>
|
397
|
-
|
398
|
-
## Usage
|
399
|
-
|
400
|
-
**Suitable for:**
|
401
|
-
- Complex interdependent business rules
|
402
|
-
- Tax calculation engines
|
403
|
-
- Insurance premium calculators
|
404
|
-
- Commission structures with complex tiers
|
405
|
-
- Pricing engines with multiple discount rules
|
406
|
-
|
407
|
-
**Not suitable for:**
|
408
|
-
- Basic conditional statements
|
409
|
-
- Sequential procedural workflows
|
410
|
-
- High-frequency processing
|
411
|
-
|
412
|
-
## Performance
|
413
190
|
|
414
|
-
|
415
|
-
- 50-deep dependency chain: **740,000/sec** (analysis <50ms)
|
416
|
-
- 1,000 attributes: **131,000/sec** (analysis <50ms)
|
417
|
-
- 10,000 attributes: **14,200/sec** (analysis ~300ms)
|
418
|
-
|
419
|
-
See [docs/features/performance.md](docs/features/performance.md) for detailed benchmarks.
|
420
|
-
|
421
|
-
## What Kumi does not guarantee
|
191
|
+
</details>
|
422
192
|
|
423
|
-
|
193
|
+
---
|
424
194
|
|
425
|
-
##
|
195
|
+
## Install
|
426
196
|
|
427
|
-
|
428
|
-
|
197
|
+
```bash
|
198
|
+
gem install kumi
|
199
|
+
```
|
429
200
|
|
430
|
-
|
201
|
+
Requires Ruby 3.1+. No external dependencies.
|
431
202
|
|
432
|
-
|
203
|
+
---
|
433
204
|
|
434
205
|
## License
|
435
206
|
|
436
|
-
MIT License. See [LICENSE](LICENSE).
|
207
|
+
MIT License. See [LICENSE](LICENSE).
|
@@ -0,0 +1,14 @@
|
|
1
|
+
functions:
|
2
|
+
- id: agg.any
|
3
|
+
kind: reduce
|
4
|
+
params: [{ name: source_value }]
|
5
|
+
dtype: "boolean"
|
6
|
+
aliases: ["any", "any?"]
|
7
|
+
folding_class_method: any?
|
8
|
+
|
9
|
+
- id: agg.all
|
10
|
+
kind: reduce
|
11
|
+
params: [{ name: source_value }]
|
12
|
+
dtype: "boolean"
|
13
|
+
aliases: ["all", "all?"]
|
14
|
+
folding_class_method: all?
|
@@ -0,0 +1,80 @@
|
|
1
|
+
functions:
|
2
|
+
- id: agg.sum
|
3
|
+
kind: reduce
|
4
|
+
params: [{ name: source_value }]
|
5
|
+
dtype: "same_as(source_value)"
|
6
|
+
reduction_strategy: identity # This function has a true identity value.
|
7
|
+
aliases: ["sum"]
|
8
|
+
|
9
|
+
- id: agg.count
|
10
|
+
kind: reduce
|
11
|
+
params: [{ name: source_value }]
|
12
|
+
dtype: "integer"
|
13
|
+
reduction_strategy: identity # This function has a true identity value.
|
14
|
+
aliases: ["count"]
|
15
|
+
|
16
|
+
- id: agg.min
|
17
|
+
kind: reduce
|
18
|
+
params: [{ name: source_value }]
|
19
|
+
dtype: "element_of(source_value)"
|
20
|
+
reduction_strategy: first_element
|
21
|
+
aliases: ["min"]
|
22
|
+
|
23
|
+
- id: agg.max
|
24
|
+
kind: reduce
|
25
|
+
params: [{ name: source_value }]
|
26
|
+
dtype: "element_of(source_value)"
|
27
|
+
reduction_strategy: first_element
|
28
|
+
aliases: ["max"]
|
29
|
+
|
30
|
+
- id: agg.mean
|
31
|
+
kind: reduce
|
32
|
+
params: [{ name: source_value }]
|
33
|
+
dtype: "float"
|
34
|
+
aliases: ["mean", "avg"]
|
35
|
+
expand:
|
36
|
+
fn: div
|
37
|
+
args:
|
38
|
+
- fn: sum
|
39
|
+
args: [ "$1" ] # $1 is source_value
|
40
|
+
- fn: count
|
41
|
+
args: [ "$1" ]
|
42
|
+
|
43
|
+
- id: agg.sum_if
|
44
|
+
kind: reduce
|
45
|
+
params: [{ name: source_value }, { name: condition }]
|
46
|
+
dtype: "same_as(source_value)"
|
47
|
+
aliases: ["sum_if"]
|
48
|
+
expand:
|
49
|
+
fn: sum
|
50
|
+
args:
|
51
|
+
- fn: __select__
|
52
|
+
args: [ "$2", "$1", { const: 0 } ] # $1=source_value, $2=condition
|
53
|
+
|
54
|
+
- id: agg.count_if
|
55
|
+
kind: reduce
|
56
|
+
params: [{ name: condition }, { name: source_value }]
|
57
|
+
dtype: "integer"
|
58
|
+
aliases: ["count_if"]
|
59
|
+
expand:
|
60
|
+
fn: sum # Summing 1s and 0s is equivalent to a conditional count
|
61
|
+
args:
|
62
|
+
- fn: __select__
|
63
|
+
args:
|
64
|
+
- fn: eq
|
65
|
+
args: ["$1", "$2"]
|
66
|
+
- { const: 1 }
|
67
|
+
- { const: 0 }
|
68
|
+
|
69
|
+
- id: agg.mean_if
|
70
|
+
kind: reduce
|
71
|
+
params: [{ name: source_value }, { name: condition }]
|
72
|
+
dtype: "float"
|
73
|
+
aliases: ["avg_if", "mean_if"]
|
74
|
+
expand:
|
75
|
+
fn: div
|
76
|
+
args:
|
77
|
+
- fn: sum_if
|
78
|
+
args: [ "$1", "$2" ] # Sum the values where the condition is true
|
79
|
+
- fn: count_if
|
80
|
+
args: [ "$1", "$2" ] # Count the values where the condition is true
|