kumi 0.0.17 → 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.
Files changed (676) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +28 -0
  5. data/CLAUDE.md +26 -139
  6. data/README.md +143 -372
  7. data/data/functions/agg/boolean.yaml +14 -0
  8. data/data/functions/agg/numeric.yaml +80 -0
  9. data/data/functions/agg/string.yaml +8 -0
  10. data/data/functions/core/arithmetic.yaml +50 -0
  11. data/data/functions/core/boolean.yaml +18 -0
  12. data/data/functions/core/comparison.yaml +42 -0
  13. data/data/functions/core/constructor.yaml +32 -0
  14. data/data/functions/core/select.yaml +7 -0
  15. data/data/functions/core/stencil.yaml +21 -0
  16. data/data/functions/core/string.yaml +19 -0
  17. data/data/kernels/javascript/agg/boolean.yaml +12 -0
  18. data/data/kernels/javascript/agg/numeric.yaml +27 -0
  19. data/data/kernels/javascript/agg/string.yaml +5 -0
  20. data/data/kernels/javascript/core/arithmetic.yaml +32 -0
  21. data/data/kernels/javascript/core/boolean.yaml +12 -0
  22. data/data/kernels/javascript/core/comparison.yaml +24 -0
  23. data/data/kernels/javascript/core/constructor.yaml +15 -0
  24. data/data/kernels/javascript/core/select.yaml +7 -0
  25. data/data/kernels/javascript/core/string.yaml +12 -0
  26. data/data/kernels/ruby/agg/boolean.yaml +18 -0
  27. data/data/kernels/ruby/agg/numeric.yaml +29 -0
  28. data/data/kernels/ruby/agg/string.yaml +5 -0
  29. data/data/kernels/ruby/core/arithmetic.yaml +38 -0
  30. data/data/kernels/ruby/core/boolean.yaml +15 -0
  31. data/data/kernels/ruby/core/comparison.yaml +30 -0
  32. data/data/kernels/ruby/core/constructor.yaml +17 -0
  33. data/data/kernels/ruby/core/select.yaml +4 -0
  34. data/data/kernels/ruby/core/string.yaml +15 -0
  35. data/debug_ordering.rb +52 -0
  36. data/docs/FORM_SCHEMA.md +85 -0
  37. data/docs/OUTPUT_SCHEMA.md +69 -0
  38. data/docs/SYNTAX.md +626 -373
  39. data/golden/array_element/expected/ast.txt +21 -0
  40. data/golden/array_element/expected/input_plan.txt +5 -0
  41. data/golden/array_element/expected/lir_00_unoptimized.txt +13 -0
  42. data/golden/array_element/expected/lir_01_hoist_scalar_references.txt +13 -0
  43. data/golden/array_element/expected/lir_02_inlined.txt +13 -0
  44. data/golden/array_element/expected/lir_03_cse.txt +13 -0
  45. data/golden/array_element/expected/lir_04_1_loop_fusion.txt +13 -0
  46. data/golden/array_element/expected/lir_04_loop_invcm.txt +13 -0
  47. data/golden/array_element/expected/lir_06_const_prop.txt +13 -0
  48. data/golden/array_element/expected/nast.txt +7 -0
  49. data/golden/array_element/expected/schema_javascript.mjs +13 -0
  50. data/golden/array_element/expected/schema_ruby.rb +41 -0
  51. data/golden/array_element/expected/snast.txt +7 -0
  52. data/golden/array_element/expected.json +5 -0
  53. data/golden/array_element/input.json +9 -0
  54. data/golden/array_element/schema.kumi +11 -0
  55. data/golden/array_index/expected/ast.txt +59 -0
  56. data/golden/array_index/expected/input_plan.txt +5 -0
  57. data/golden/array_index/expected/lir_00_unoptimized.txt +41 -0
  58. data/golden/array_index/expected/lir_01_hoist_scalar_references.txt +41 -0
  59. data/golden/array_index/expected/lir_02_inlined.txt +42 -0
  60. data/golden/array_index/expected/lir_03_cse.txt +40 -0
  61. data/golden/array_index/expected/lir_04_1_loop_fusion.txt +40 -0
  62. data/golden/array_index/expected/lir_04_loop_invcm.txt +40 -0
  63. data/golden/array_index/expected/lir_06_const_prop.txt +40 -0
  64. data/golden/array_index/expected/nast.txt +33 -0
  65. data/golden/array_index/expected/schema_javascript.mjs +46 -0
  66. data/golden/array_index/expected/schema_ruby.rb +75 -0
  67. data/golden/array_index/expected/snast.txt +33 -0
  68. data/golden/array_index/expected.json +5 -0
  69. data/golden/array_index/input.json +1 -0
  70. data/golden/array_index/schema.kumi +19 -0
  71. data/golden/array_operations/expected/ast.txt +50 -0
  72. data/golden/array_operations/expected/input_plan.txt +10 -0
  73. data/golden/array_operations/expected/lir_00_unoptimized.txt +47 -0
  74. data/golden/array_operations/expected/lir_01_hoist_scalar_references.txt +47 -0
  75. data/golden/array_operations/expected/lir_02_inlined.txt +47 -0
  76. data/golden/array_operations/expected/lir_03_cse.txt +47 -0
  77. data/golden/array_operations/expected/lir_04_1_loop_fusion.txt +47 -0
  78. data/golden/array_operations/expected/lir_04_loop_invcm.txt +47 -0
  79. data/golden/array_operations/expected/lir_06_const_prop.txt +47 -0
  80. data/golden/array_operations/expected/nast.txt +32 -0
  81. data/golden/array_operations/expected/schema_javascript.mjs +60 -0
  82. data/golden/array_operations/expected/schema_ruby.rb +91 -0
  83. data/golden/array_operations/expected/snast.txt +32 -0
  84. data/golden/array_operations/expected.json +27 -0
  85. data/golden/array_operations/input.json +8 -0
  86. data/golden/array_operations/schema.kumi +12 -10
  87. data/golden/cascade_logic/expected/ast.txt +37 -0
  88. data/golden/cascade_logic/expected/input_plan.txt +2 -0
  89. data/golden/cascade_logic/expected/lir_00_unoptimized.txt +29 -0
  90. data/golden/cascade_logic/expected/lir_01_hoist_scalar_references.txt +29 -0
  91. data/golden/cascade_logic/expected/lir_02_inlined.txt +37 -0
  92. data/golden/cascade_logic/expected/lir_03_cse.txt +30 -0
  93. data/golden/cascade_logic/expected/lir_04_1_loop_fusion.txt +30 -0
  94. data/golden/cascade_logic/expected/lir_04_loop_invcm.txt +30 -0
  95. data/golden/cascade_logic/expected/lir_06_const_prop.txt +30 -0
  96. data/golden/cascade_logic/expected/nast.txt +32 -0
  97. data/golden/cascade_logic/expected/schema_javascript.mjs +31 -0
  98. data/golden/cascade_logic/expected/schema_ruby.rb +57 -0
  99. data/golden/cascade_logic/expected/snast.txt +32 -0
  100. data/golden/cascade_logic/expected.json +5 -0
  101. data/golden/cascade_logic/input.json +4 -0
  102. data/golden/cascade_logic/schema.kumi +1 -3
  103. data/golden/chained_fusion/expected/ast.txt +57 -0
  104. data/golden/chained_fusion/expected/input_plan.txt +13 -0
  105. data/golden/chained_fusion/expected/lir_00_unoptimized.txt +76 -0
  106. data/golden/chained_fusion/expected/lir_01_hoist_scalar_references.txt +76 -0
  107. data/golden/chained_fusion/expected/lir_02_inlined.txt +114 -0
  108. data/golden/chained_fusion/expected/lir_03_cse.txt +97 -0
  109. data/golden/chained_fusion/expected/lir_04_1_loop_fusion.txt +99 -0
  110. data/golden/chained_fusion/expected/lir_04_loop_invcm.txt +97 -0
  111. data/golden/chained_fusion/expected/lir_06_const_prop.txt +97 -0
  112. data/golden/chained_fusion/expected/nast.txt +55 -0
  113. data/golden/chained_fusion/expected/schema_javascript.mjs +116 -0
  114. data/golden/chained_fusion/expected/schema_ruby.rb +149 -0
  115. data/golden/chained_fusion/expected/snast.txt +55 -0
  116. data/golden/chained_fusion/expected.json +45 -0
  117. data/golden/chained_fusion/input.json +51 -0
  118. data/golden/chained_fusion/schema.kumi +52 -0
  119. data/golden/element_arrays/expected/ast.txt +55 -0
  120. data/golden/element_arrays/expected/input_plan.txt +7 -0
  121. data/golden/element_arrays/expected/lir_00_unoptimized.txt +81 -0
  122. data/golden/element_arrays/expected/lir_01_hoist_scalar_references.txt +81 -0
  123. data/golden/element_arrays/expected/lir_02_inlined.txt +85 -0
  124. data/golden/element_arrays/expected/lir_03_cse.txt +83 -0
  125. data/golden/element_arrays/expected/lir_04_1_loop_fusion.txt +83 -0
  126. data/golden/element_arrays/expected/lir_04_loop_invcm.txt +83 -0
  127. data/golden/element_arrays/expected/lir_06_const_prop.txt +83 -0
  128. data/golden/element_arrays/expected/nast.txt +42 -0
  129. data/golden/element_arrays/expected/schema_javascript.mjs +106 -0
  130. data/golden/element_arrays/expected/schema_ruby.rb +141 -0
  131. data/golden/element_arrays/expected/snast.txt +42 -0
  132. data/golden/element_arrays/expected.json +55 -0
  133. data/golden/element_arrays/input.json +12 -0
  134. data/golden/element_arrays/schema.kumi +21 -0
  135. data/golden/empty_and_null_inputs/expected/ast.txt +42 -0
  136. data/golden/empty_and_null_inputs/expected/input_plan.txt +12 -0
  137. data/golden/empty_and_null_inputs/expected/lir_00_unoptimized.txt +31 -0
  138. data/golden/empty_and_null_inputs/expected/lir_01_hoist_scalar_references.txt +31 -0
  139. data/golden/empty_and_null_inputs/expected/lir_02_inlined.txt +51 -0
  140. data/golden/empty_and_null_inputs/expected/lir_03_cse.txt +49 -0
  141. data/golden/empty_and_null_inputs/expected/lir_04_1_loop_fusion.txt +49 -0
  142. data/golden/empty_and_null_inputs/expected/lir_04_loop_invcm.txt +49 -0
  143. data/golden/empty_and_null_inputs/expected/lir_06_const_prop.txt +49 -0
  144. data/golden/empty_and_null_inputs/expected/nast.txt +18 -0
  145. data/golden/empty_and_null_inputs/expected/schema_javascript.mjs +47 -0
  146. data/golden/empty_and_null_inputs/expected/schema_ruby.rb +79 -0
  147. data/golden/empty_and_null_inputs/expected/snast.txt +18 -0
  148. data/golden/empty_and_null_inputs/expected.json +8 -0
  149. data/golden/empty_and_null_inputs/input.json +16 -0
  150. data/golden/empty_and_null_inputs/schema.kumi +30 -0
  151. data/golden/game_of_life/expected/ast.txt +118 -0
  152. data/golden/game_of_life/expected/input_plan.txt +5 -0
  153. data/golden/game_of_life/expected/lir_00_unoptimized.txt +343 -0
  154. data/golden/game_of_life/expected/lir_01_hoist_scalar_references.txt +343 -0
  155. data/golden/game_of_life/expected/lir_02_inlined.txt +1918 -0
  156. data/golden/game_of_life/expected/lir_03_cse.txt +766 -0
  157. data/golden/game_of_life/expected/lir_04_1_loop_fusion.txt +766 -0
  158. data/golden/game_of_life/expected/lir_04_loop_invcm.txt +766 -0
  159. data/golden/game_of_life/expected/lir_06_const_prop.txt +766 -0
  160. data/golden/game_of_life/expected/nast.txt +104 -0
  161. data/golden/game_of_life/expected/schema_javascript.mjs +98 -0
  162. data/golden/game_of_life/expected/schema_ruby.rb +125 -0
  163. data/golden/game_of_life/expected/snast.txt +104 -0
  164. data/golden/game_of_life/expected.json +3 -0
  165. data/golden/game_of_life/input.json +8 -0
  166. data/golden/game_of_life/schema.kumi +33 -0
  167. data/golden/hash_keys/expected/ast.txt +29 -0
  168. data/golden/hash_keys/expected/input_plan.txt +2 -0
  169. data/golden/hash_keys/expected/lir_00_unoptimized.txt +18 -0
  170. data/golden/hash_keys/expected/lir_01_hoist_scalar_references.txt +18 -0
  171. data/golden/hash_keys/expected/lir_02_inlined.txt +18 -0
  172. data/golden/hash_keys/expected/lir_03_cse.txt +18 -0
  173. data/golden/hash_keys/expected/lir_04_1_loop_fusion.txt +18 -0
  174. data/golden/hash_keys/expected/lir_04_loop_invcm.txt +18 -0
  175. data/golden/hash_keys/expected/lir_06_const_prop.txt +18 -0
  176. data/golden/hash_keys/expected/nast.txt +46 -0
  177. data/golden/hash_keys/expected/schema_javascript.mjs +34 -0
  178. data/golden/hash_keys/expected/schema_ruby.rb +61 -0
  179. data/golden/hash_keys/expected/snast.txt +46 -0
  180. data/golden/hash_keys/expected.json +20 -0
  181. data/golden/hash_keys/input.json +4 -0
  182. data/golden/hash_keys/schema.kumi +14 -0
  183. data/golden/hash_value/expected/ast.txt +37 -0
  184. data/golden/hash_value/expected/input_plan.txt +7 -0
  185. data/golden/hash_value/expected/lir_00_unoptimized.txt +30 -0
  186. data/golden/hash_value/expected/lir_01_hoist_scalar_references.txt +30 -0
  187. data/golden/hash_value/expected/lir_02_inlined.txt +36 -0
  188. data/golden/hash_value/expected/lir_03_cse.txt +33 -0
  189. data/golden/hash_value/expected/lir_04_1_loop_fusion.txt +33 -0
  190. data/golden/hash_value/expected/lir_04_loop_invcm.txt +33 -0
  191. data/golden/hash_value/expected/lir_06_const_prop.txt +33 -0
  192. data/golden/hash_value/expected/nast.txt +25 -0
  193. data/golden/hash_value/expected/schema_javascript.mjs +46 -0
  194. data/golden/hash_value/expected/schema_ruby.rb +75 -0
  195. data/golden/hash_value/expected/snast.txt +25 -0
  196. data/golden/hash_value/expected.json +19 -0
  197. data/golden/hash_value/input.json +12 -0
  198. data/golden/hash_value/schema.kumi +19 -0
  199. data/golden/hierarchical_complex/expected/ast.txt +85 -0
  200. data/golden/hierarchical_complex/expected/input_plan.txt +23 -0
  201. data/golden/hierarchical_complex/expected/lir_00_unoptimized.txt +87 -0
  202. data/golden/hierarchical_complex/expected/lir_01_hoist_scalar_references.txt +87 -0
  203. data/golden/hierarchical_complex/expected/lir_02_inlined.txt +115 -0
  204. data/golden/hierarchical_complex/expected/lir_03_cse.txt +89 -0
  205. data/golden/hierarchical_complex/expected/lir_04_1_loop_fusion.txt +89 -0
  206. data/golden/hierarchical_complex/expected/lir_04_loop_invcm.txt +89 -0
  207. data/golden/hierarchical_complex/expected/lir_06_const_prop.txt +89 -0
  208. data/golden/hierarchical_complex/expected/nast.txt +49 -0
  209. data/golden/hierarchical_complex/expected/schema_javascript.mjs +121 -0
  210. data/golden/hierarchical_complex/expected/schema_ruby.rb +151 -0
  211. data/golden/hierarchical_complex/expected/snast.txt +49 -0
  212. data/golden/hierarchical_complex/expected.json +34 -0
  213. data/golden/hierarchical_complex/input.json +26 -0
  214. data/golden/hierarchical_complex/schema.kumi +38 -0
  215. data/golden/input_reference/expected/ast.txt +46 -0
  216. data/golden/input_reference/expected/input_plan.txt +15 -0
  217. data/golden/input_reference/expected/lir_00_unoptimized.txt +39 -0
  218. data/golden/input_reference/expected/lir_01_hoist_scalar_references.txt +39 -0
  219. data/golden/input_reference/expected/lir_02_inlined.txt +39 -0
  220. data/golden/input_reference/expected/lir_03_cse.txt +39 -0
  221. data/golden/input_reference/expected/lir_04_1_loop_fusion.txt +39 -0
  222. data/golden/input_reference/expected/lir_04_loop_invcm.txt +39 -0
  223. data/golden/input_reference/expected/lir_06_const_prop.txt +39 -0
  224. data/golden/input_reference/expected/nast.txt +21 -0
  225. data/golden/input_reference/expected/schema_javascript.mjs +45 -0
  226. data/golden/input_reference/expected/schema_ruby.rb +74 -0
  227. data/golden/input_reference/expected/snast.txt +21 -0
  228. data/golden/input_reference/expected.json +7 -0
  229. data/golden/input_reference/input.json +11 -0
  230. data/golden/input_reference/schema.kumi +22 -0
  231. data/golden/interleaved_fusion/expected/ast.txt +51 -0
  232. data/golden/interleaved_fusion/expected/input_plan.txt +13 -0
  233. data/golden/interleaved_fusion/expected/lir_00_unoptimized.txt +53 -0
  234. data/golden/interleaved_fusion/expected/lir_01_hoist_scalar_references.txt +53 -0
  235. data/golden/interleaved_fusion/expected/lir_02_inlined.txt +89 -0
  236. data/golden/interleaved_fusion/expected/lir_03_cse.txt +77 -0
  237. data/golden/interleaved_fusion/expected/lir_04_1_loop_fusion.txt +77 -0
  238. data/golden/interleaved_fusion/expected/lir_04_loop_invcm.txt +77 -0
  239. data/golden/interleaved_fusion/expected/lir_06_const_prop.txt +77 -0
  240. data/golden/interleaved_fusion/expected/nast.txt +41 -0
  241. data/golden/interleaved_fusion/expected/schema_javascript.mjs +86 -0
  242. data/golden/interleaved_fusion/expected/schema_ruby.rb +122 -0
  243. data/golden/interleaved_fusion/expected/snast.txt +41 -0
  244. data/golden/interleaved_fusion/expected.json +37 -0
  245. data/golden/interleaved_fusion/input.json +26 -0
  246. data/golden/interleaved_fusion/schema.kumi +57 -0
  247. data/golden/let_inline/expected/ast.txt +33 -0
  248. data/golden/let_inline/expected/input_plan.txt +2 -0
  249. data/golden/let_inline/expected/lir_00_unoptimized.txt +26 -0
  250. data/golden/let_inline/expected/lir_01_hoist_scalar_references.txt +26 -0
  251. data/golden/let_inline/expected/lir_02_inlined.txt +36 -0
  252. data/golden/let_inline/expected/lir_03_cse.txt +30 -0
  253. data/golden/let_inline/expected/lir_04_1_loop_fusion.txt +30 -0
  254. data/golden/let_inline/expected/lir_04_loop_invcm.txt +30 -0
  255. data/golden/let_inline/expected/lir_06_const_prop.txt +30 -0
  256. data/golden/let_inline/expected/nast.txt +26 -0
  257. data/golden/let_inline/expected/schema_javascript.mjs +11 -0
  258. data/golden/let_inline/expected/schema_ruby.rb +37 -0
  259. data/golden/let_inline/expected/snast.txt +26 -0
  260. data/golden/let_inline/expected.json +1 -0
  261. data/golden/let_inline/input.json +1 -0
  262. data/golden/let_inline/schema.kumi +11 -0
  263. data/golden/loop_fusion/expected/ast.txt +44 -0
  264. data/golden/loop_fusion/expected/input_plan.txt +13 -0
  265. data/golden/loop_fusion/expected/lir_00_unoptimized.txt +43 -0
  266. data/golden/loop_fusion/expected/lir_01_hoist_scalar_references.txt +43 -0
  267. data/golden/loop_fusion/expected/lir_02_inlined.txt +62 -0
  268. data/golden/loop_fusion/expected/lir_03_cse.txt +57 -0
  269. data/golden/loop_fusion/expected/lir_04_1_loop_fusion.txt +57 -0
  270. data/golden/loop_fusion/expected/lir_04_loop_invcm.txt +57 -0
  271. data/golden/loop_fusion/expected/lir_06_const_prop.txt +57 -0
  272. data/golden/loop_fusion/expected/nast.txt +32 -0
  273. data/golden/loop_fusion/expected/schema_javascript.mjs +64 -0
  274. data/golden/loop_fusion/expected/schema_ruby.rb +97 -0
  275. data/golden/loop_fusion/expected/snast.txt +32 -0
  276. data/golden/loop_fusion/expected.json +30 -0
  277. data/golden/loop_fusion/input.json +28 -0
  278. data/golden/loop_fusion/schema.kumi +32 -0
  279. data/golden/min_reduce_scope/expected/ast.txt +49 -0
  280. data/golden/min_reduce_scope/expected/input_plan.txt +9 -0
  281. data/golden/min_reduce_scope/expected/lir_00_unoptimized.txt +59 -0
  282. data/golden/min_reduce_scope/expected/lir_01_hoist_scalar_references.txt +59 -0
  283. data/golden/min_reduce_scope/expected/lir_02_inlined.txt +63 -0
  284. data/golden/min_reduce_scope/expected/lir_03_cse.txt +60 -0
  285. data/golden/min_reduce_scope/expected/lir_04_1_loop_fusion.txt +60 -0
  286. data/golden/min_reduce_scope/expected/lir_04_loop_invcm.txt +60 -0
  287. data/golden/min_reduce_scope/expected/lir_06_const_prop.txt +60 -0
  288. data/golden/min_reduce_scope/expected/nast.txt +29 -0
  289. data/golden/min_reduce_scope/expected/schema_javascript.mjs +66 -0
  290. data/golden/min_reduce_scope/expected/schema_ruby.rb +99 -0
  291. data/golden/min_reduce_scope/expected/snast.txt +29 -0
  292. data/golden/min_reduce_scope/expected.json +9 -0
  293. data/golden/min_reduce_scope/input.json +18 -0
  294. data/golden/min_reduce_scope/schema.kumi +25 -0
  295. data/golden/mixed_dimensions/expected/ast.txt +54 -0
  296. data/golden/mixed_dimensions/expected/input_plan.txt +15 -0
  297. data/golden/mixed_dimensions/expected/lir_00_unoptimized.txt +42 -0
  298. data/golden/mixed_dimensions/expected/lir_01_hoist_scalar_references.txt +42 -0
  299. data/golden/mixed_dimensions/expected/lir_02_inlined.txt +48 -0
  300. data/golden/mixed_dimensions/expected/lir_03_cse.txt +48 -0
  301. data/golden/mixed_dimensions/expected/lir_04_1_loop_fusion.txt +48 -0
  302. data/golden/mixed_dimensions/expected/lir_04_loop_invcm.txt +48 -0
  303. data/golden/mixed_dimensions/expected/lir_06_const_prop.txt +48 -0
  304. data/golden/mixed_dimensions/expected/nast.txt +22 -0
  305. data/golden/mixed_dimensions/expected/schema_javascript.mjs +53 -0
  306. data/golden/mixed_dimensions/expected/schema_ruby.rb +84 -0
  307. data/golden/mixed_dimensions/expected/snast.txt +22 -0
  308. data/golden/mixed_dimensions/expected.json +6 -0
  309. data/golden/mixed_dimensions/input.json +22 -0
  310. data/golden/mixed_dimensions/schema.kumi +35 -0
  311. data/golden/multirank_hoisting/expected/ast.txt +72 -0
  312. data/golden/multirank_hoisting/expected/input_plan.txt +18 -0
  313. data/golden/multirank_hoisting/expected/lir_00_unoptimized.txt +75 -0
  314. data/golden/multirank_hoisting/expected/lir_01_hoist_scalar_references.txt +75 -0
  315. data/golden/multirank_hoisting/expected/lir_02_inlined.txt +126 -0
  316. data/golden/multirank_hoisting/expected/lir_03_cse.txt +109 -0
  317. data/golden/multirank_hoisting/expected/lir_04_1_loop_fusion.txt +109 -0
  318. data/golden/multirank_hoisting/expected/lir_04_loop_invcm.txt +109 -0
  319. data/golden/multirank_hoisting/expected/lir_06_const_prop.txt +109 -0
  320. data/golden/multirank_hoisting/expected/nast.txt +39 -0
  321. data/golden/multirank_hoisting/expected/schema_javascript.mjs +128 -0
  322. data/golden/multirank_hoisting/expected/schema_ruby.rb +162 -0
  323. data/golden/multirank_hoisting/expected/snast.txt +39 -0
  324. data/golden/multirank_hoisting/expected.json +15 -0
  325. data/golden/multirank_hoisting/input.json +19 -0
  326. data/golden/multirank_hoisting/schema.kumi +38 -0
  327. data/golden/nested_hash/expected/ast.txt +22 -0
  328. data/golden/nested_hash/expected/input_plan.txt +5 -0
  329. data/golden/nested_hash/expected/lir_00_unoptimized.txt +10 -0
  330. data/golden/nested_hash/expected/lir_01_hoist_scalar_references.txt +10 -0
  331. data/golden/nested_hash/expected/lir_02_inlined.txt +10 -0
  332. data/golden/nested_hash/expected/lir_03_cse.txt +10 -0
  333. data/golden/nested_hash/expected/lir_04_1_loop_fusion.txt +10 -0
  334. data/golden/nested_hash/expected/lir_04_loop_invcm.txt +10 -0
  335. data/golden/nested_hash/expected/lir_06_const_prop.txt +10 -0
  336. data/golden/nested_hash/expected/nast.txt +8 -0
  337. data/golden/nested_hash/expected/schema_javascript.mjs +9 -0
  338. data/golden/nested_hash/expected/schema_ruby.rb +35 -0
  339. data/golden/nested_hash/expected/snast.txt +8 -0
  340. data/golden/nested_hash/expected.json +3 -0
  341. data/golden/nested_hash/input.json +7 -0
  342. data/golden/nested_hash/schema.kumi +11 -0
  343. data/golden/reduction_broadcast/expected/ast.txt +49 -0
  344. data/golden/reduction_broadcast/expected/input_plan.txt +13 -0
  345. data/golden/reduction_broadcast/expected/lir_00_unoptimized.txt +49 -0
  346. data/golden/reduction_broadcast/expected/lir_01_hoist_scalar_references.txt +49 -0
  347. data/golden/reduction_broadcast/expected/lir_02_inlined.txt +80 -0
  348. data/golden/reduction_broadcast/expected/lir_03_cse.txt +68 -0
  349. data/golden/reduction_broadcast/expected/lir_04_1_loop_fusion.txt +68 -0
  350. data/golden/reduction_broadcast/expected/lir_04_loop_invcm.txt +68 -0
  351. data/golden/reduction_broadcast/expected/lir_06_const_prop.txt +68 -0
  352. data/golden/reduction_broadcast/expected/nast.txt +24 -0
  353. data/golden/reduction_broadcast/expected/schema_javascript.mjs +74 -0
  354. data/golden/reduction_broadcast/expected/schema_ruby.rb +110 -0
  355. data/golden/reduction_broadcast/expected/snast.txt +24 -0
  356. data/golden/reduction_broadcast/expected.json +25 -0
  357. data/golden/reduction_broadcast/input.json +19 -0
  358. data/golden/reduction_broadcast/schema.kumi +34 -0
  359. data/golden/roll/expected/ast.txt +36 -0
  360. data/golden/roll/expected/input_plan.txt +3 -0
  361. data/golden/roll/expected/lir_00_unoptimized.txt +56 -0
  362. data/golden/roll/expected/lir_01_hoist_scalar_references.txt +56 -0
  363. data/golden/roll/expected/lir_02_inlined.txt +56 -0
  364. data/golden/roll/expected/lir_03_cse.txt +55 -0
  365. data/golden/roll/expected/lir_04_1_loop_fusion.txt +55 -0
  366. data/golden/roll/expected/lir_04_loop_invcm.txt +55 -0
  367. data/golden/roll/expected/lir_06_const_prop.txt +55 -0
  368. data/golden/roll/expected/nast.txt +26 -0
  369. data/golden/roll/expected/schema_javascript.mjs +65 -0
  370. data/golden/roll/expected/schema_ruby.rb +95 -0
  371. data/golden/roll/expected/snast.txt +26 -0
  372. data/golden/roll/expected.json +6 -0
  373. data/golden/roll/input.json +1 -0
  374. data/golden/roll/schema.kumi +13 -0
  375. data/golden/shift/expected/ast.txt +48 -0
  376. data/golden/shift/expected/input_plan.txt +3 -0
  377. data/golden/shift/expected/lir_00_unoptimized.txt +96 -0
  378. data/golden/shift/expected/lir_01_hoist_scalar_references.txt +96 -0
  379. data/golden/shift/expected/lir_02_inlined.txt +96 -0
  380. data/golden/shift/expected/lir_03_cse.txt +90 -0
  381. data/golden/shift/expected/lir_04_1_loop_fusion.txt +90 -0
  382. data/golden/shift/expected/lir_04_loop_invcm.txt +90 -0
  383. data/golden/shift/expected/lir_06_const_prop.txt +90 -0
  384. data/golden/shift/expected/nast.txt +38 -0
  385. data/golden/shift/expected/schema_javascript.mjs +106 -0
  386. data/golden/shift/expected/schema_ruby.rb +138 -0
  387. data/golden/shift/expected/snast.txt +38 -0
  388. data/golden/shift/expected.json +8 -0
  389. data/golden/shift/input.json +1 -0
  390. data/golden/shift/schema.kumi +15 -0
  391. data/golden/shift_2d/expected/ast.txt +88 -0
  392. data/golden/shift_2d/expected/input_plan.txt +5 -0
  393. data/golden/shift_2d/expected/lir_00_unoptimized.txt +274 -0
  394. data/golden/shift_2d/expected/lir_01_hoist_scalar_references.txt +274 -0
  395. data/golden/shift_2d/expected/lir_02_inlined.txt +274 -0
  396. data/golden/shift_2d/expected/lir_03_cse.txt +262 -0
  397. data/golden/shift_2d/expected/lir_04_1_loop_fusion.txt +262 -0
  398. data/golden/shift_2d/expected/lir_04_loop_invcm.txt +262 -0
  399. data/golden/shift_2d/expected/lir_06_const_prop.txt +262 -0
  400. data/golden/shift_2d/expected/nast.txt +74 -0
  401. data/golden/shift_2d/expected/schema_javascript.mjs +320 -0
  402. data/golden/shift_2d/expected/schema_ruby.rb +358 -0
  403. data/golden/shift_2d/expected/snast.txt +74 -0
  404. data/golden/shift_2d/expected.json +15 -0
  405. data/golden/shift_2d/input.json +14 -0
  406. data/golden/shift_2d/schema.kumi +25 -0
  407. data/golden/simple_math/expected/ast.txt +40 -0
  408. data/golden/simple_math/expected/input_plan.txt +2 -0
  409. data/golden/simple_math/expected/lir_00_unoptimized.txt +31 -0
  410. data/golden/simple_math/expected/lir_01_hoist_scalar_references.txt +31 -0
  411. data/golden/simple_math/expected/lir_02_inlined.txt +31 -0
  412. data/golden/simple_math/expected/lir_03_cse.txt +31 -0
  413. data/golden/simple_math/expected/lir_04_1_loop_fusion.txt +31 -0
  414. data/golden/simple_math/expected/lir_04_loop_invcm.txt +31 -0
  415. data/golden/simple_math/expected/lir_06_const_prop.txt +31 -0
  416. data/golden/simple_math/expected/nast.txt +33 -0
  417. data/golden/simple_math/expected/schema_javascript.mjs +33 -0
  418. data/golden/simple_math/expected/schema_ruby.rb +59 -0
  419. data/golden/simple_math/expected/snast.txt +33 -0
  420. data/golden/simple_math/expected.json +1 -0
  421. data/golden/simple_math/input.json +4 -0
  422. data/golden/simple_math/schema.kumi +2 -1
  423. data/golden/streaming_basics/expected/ast.txt +64 -0
  424. data/golden/streaming_basics/expected/input_plan.txt +8 -0
  425. data/golden/streaming_basics/expected/lir_00_unoptimized.txt +73 -0
  426. data/golden/streaming_basics/expected/lir_01_hoist_scalar_references.txt +73 -0
  427. data/golden/streaming_basics/expected/lir_02_inlined.txt +100 -0
  428. data/golden/streaming_basics/expected/lir_03_cse.txt +84 -0
  429. data/golden/streaming_basics/expected/lir_04_1_loop_fusion.txt +84 -0
  430. data/golden/streaming_basics/expected/lir_04_loop_invcm.txt +84 -0
  431. data/golden/streaming_basics/expected/lir_06_const_prop.txt +84 -0
  432. data/golden/streaming_basics/expected/nast.txt +48 -0
  433. data/golden/streaming_basics/expected/schema_javascript.mjs +94 -0
  434. data/golden/streaming_basics/expected/schema_ruby.rb +127 -0
  435. data/golden/streaming_basics/expected/snast.txt +48 -0
  436. data/golden/streaming_basics/expected.json +10 -0
  437. data/golden/streaming_basics/input.json +8 -0
  438. data/golden/streaming_basics/schema.kumi +24 -0
  439. data/golden/tuples/expected/ast.txt +48 -0
  440. data/golden/tuples/expected/input_plan.txt +1 -0
  441. data/golden/tuples/expected/lir_00_unoptimized.txt +40 -0
  442. data/golden/tuples/expected/lir_01_hoist_scalar_references.txt +40 -0
  443. data/golden/tuples/expected/lir_02_inlined.txt +48 -0
  444. data/golden/tuples/expected/lir_03_cse.txt +48 -0
  445. data/golden/tuples/expected/lir_04_1_loop_fusion.txt +48 -0
  446. data/golden/tuples/expected/lir_04_loop_invcm.txt +48 -0
  447. data/golden/tuples/expected/lir_06_const_prop.txt +48 -0
  448. data/golden/tuples/expected/nast.txt +42 -0
  449. data/golden/tuples/expected/schema_javascript.mjs +51 -0
  450. data/golden/tuples/expected/schema_ruby.rb +77 -0
  451. data/golden/tuples/expected/snast.txt +42 -0
  452. data/golden/tuples/expected.json +7 -0
  453. data/golden/tuples/input.json +3 -0
  454. data/golden/tuples/schema.kumi +11 -0
  455. data/golden/tuples_and_arrays/expected/ast.txt +44 -0
  456. data/golden/tuples_and_arrays/expected/input_plan.txt +7 -0
  457. data/golden/tuples_and_arrays/expected/lir_00_unoptimized.txt +41 -0
  458. data/golden/tuples_and_arrays/expected/lir_01_hoist_scalar_references.txt +41 -0
  459. data/golden/tuples_and_arrays/expected/lir_02_inlined.txt +62 -0
  460. data/golden/tuples_and_arrays/expected/lir_03_cse.txt +51 -0
  461. data/golden/tuples_and_arrays/expected/lir_04_1_loop_fusion.txt +51 -0
  462. data/golden/tuples_and_arrays/expected/lir_04_loop_invcm.txt +51 -0
  463. data/golden/tuples_and_arrays/expected/lir_06_const_prop.txt +51 -0
  464. data/golden/tuples_and_arrays/expected/nast.txt +28 -0
  465. data/golden/tuples_and_arrays/expected/schema_javascript.mjs +58 -0
  466. data/golden/tuples_and_arrays/expected/schema_ruby.rb +88 -0
  467. data/golden/tuples_and_arrays/expected/snast.txt +28 -0
  468. data/golden/tuples_and_arrays/expected.json +18 -0
  469. data/golden/tuples_and_arrays/input.json +7 -0
  470. data/golden/tuples_and_arrays/schema.kumi +38 -0
  471. data/golden/with_constants/expected/ast.txt +28 -0
  472. data/golden/with_constants/expected/input_plan.txt +2 -0
  473. data/golden/with_constants/expected/lir_00_unoptimized.txt +17 -0
  474. data/golden/with_constants/expected/lir_01_hoist_scalar_references.txt +17 -0
  475. data/golden/with_constants/expected/lir_02_inlined.txt +17 -0
  476. data/golden/with_constants/expected/lir_03_cse.txt +17 -0
  477. data/golden/with_constants/expected/lir_04_1_loop_fusion.txt +17 -0
  478. data/golden/with_constants/expected/lir_04_loop_invcm.txt +17 -0
  479. data/golden/with_constants/expected/lir_06_const_prop.txt +17 -0
  480. data/golden/with_constants/expected/nast.txt +21 -0
  481. data/golden/with_constants/expected/schema_javascript.mjs +18 -0
  482. data/golden/with_constants/expected/schema_ruby.rb +44 -0
  483. data/golden/with_constants/expected/snast.txt +15 -0
  484. data/golden/with_constants/schema.kumi +10 -0
  485. data/lib/kumi/analyzer.rb +76 -24
  486. data/lib/kumi/configuration.rb +60 -0
  487. data/lib/kumi/core/analyzer/binder.rb +121 -0
  488. data/lib/kumi/core/analyzer/checkpoint.rb +15 -9
  489. data/lib/kumi/core/analyzer/constant_evaluator.rb +32 -37
  490. data/lib/kumi/core/analyzer/constant_folding_helpers.rb +55 -0
  491. data/lib/kumi/core/analyzer/debug.rb +14 -16
  492. data/lib/kumi/core/analyzer/fn_aliases.rb +46 -0
  493. data/lib/kumi/core/analyzer/folder.rb +94 -0
  494. data/lib/kumi/core/analyzer/macro_expander.rb +69 -0
  495. data/lib/kumi/core/analyzer/passes/assemble_irv2_pass.rb +130 -0
  496. data/lib/kumi/core/analyzer/passes/attach_anchors_pass.rb +71 -0
  497. data/lib/kumi/core/analyzer/passes/attach_terminal_info_pass.rb +181 -0
  498. data/lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb +317 -0
  499. data/lib/kumi/core/analyzer/passes/codegen/js/emitter.rb +75 -0
  500. data/lib/kumi/core/analyzer/passes/codegen/js/output_buffer.rb +103 -0
  501. data/lib/kumi/core/analyzer/passes/codegen/js_pass.rb +27 -0
  502. data/lib/kumi/core/analyzer/passes/codegen/ruby/declaration_emitter.rb +321 -0
  503. data/lib/kumi/core/analyzer/passes/codegen/ruby/emitter.rb +85 -0
  504. data/lib/kumi/core/analyzer/passes/codegen/ruby/output_buffer.rb +111 -0
  505. data/lib/kumi/core/analyzer/passes/codegen/ruby_pass.rb +32 -0
  506. data/lib/kumi/core/analyzer/passes/constant_folding_pass.rb +33 -0
  507. data/lib/kumi/core/analyzer/passes/contract_checker_pass.rb +220 -0
  508. data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +5 -6
  509. data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +7 -3
  510. data/lib/kumi/core/analyzer/passes/input_collector.rb +74 -122
  511. data/lib/kumi/core/analyzer/passes/input_form_schema_pass.rb +43 -0
  512. data/lib/kumi/core/analyzer/passes/ir_dependency_pass.rb +1 -1
  513. data/lib/kumi/core/analyzer/passes/ir_execution_schedule_pass.rb +1 -1
  514. data/lib/kumi/core/analyzer/passes/join_reduce_planning_pass.rb +21 -23
  515. data/lib/kumi/core/analyzer/passes/lir/constant_propagation_pass.rb +84 -0
  516. data/lib/kumi/core/analyzer/passes/lir/dead_code_elimination_pass.rb +93 -0
  517. data/lib/kumi/core/analyzer/passes/lir/hoist_scalar_references_pass.rb +115 -0
  518. data/lib/kumi/core/analyzer/passes/lir/inline_declarations_pass.rb +274 -0
  519. data/lib/kumi/core/analyzer/passes/lir/instruction_scheduling_pass.rb +198 -0
  520. data/lib/kumi/core/analyzer/passes/lir/kernel_binding_pass.rb +30 -0
  521. data/lib/kumi/core/analyzer/passes/lir/local_cse_pass.rb +121 -0
  522. data/lib/kumi/core/analyzer/passes/lir/loop_fusion_pass.rb +156 -0
  523. data/lib/kumi/core/analyzer/passes/lir/loop_invariant_code_motion_pass.rb +148 -0
  524. data/lib/kumi/core/analyzer/passes/lir/lower_pass.rb +407 -0
  525. data/lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb +243 -0
  526. data/lib/kumi/core/analyzer/passes/lir/validation_pass.rb +83 -0
  527. data/lib/kumi/core/analyzer/passes/load_input_cse.rb +17 -16
  528. data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +4 -2
  529. data/lib/kumi/core/analyzer/passes/lower_to_irv2_pass.rb +197 -0
  530. data/lib/kumi/core/analyzer/passes/name_indexer.rb +4 -1
  531. data/lib/kumi/core/analyzer/passes/nast_dimensional_analyzer_pass.rb +237 -0
  532. data/lib/kumi/core/analyzer/passes/normalize_to_nast_pass.rb +156 -0
  533. data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +38 -0
  534. data/lib/kumi/core/analyzer/passes/pass_base.rb +30 -4
  535. data/lib/kumi/core/analyzer/passes/precompute_access_paths_pass.rb +93 -0
  536. data/lib/kumi/core/analyzer/passes/scope_resolution_pass.rb +33 -30
  537. data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +5 -26
  538. data/lib/kumi/core/analyzer/passes/snast_pass.rb +229 -0
  539. data/lib/kumi/core/analyzer/passes/toposorter.rb +1 -0
  540. data/lib/kumi/core/analyzer/passes/type_checker.rb +13 -0
  541. data/lib/kumi/core/analyzer/passes/type_inferencer_pass.rb +14 -16
  542. data/lib/kumi/core/analyzer/passes/unsat_detector.rb +2 -1
  543. data/lib/kumi/core/analyzer/plans.rb +12 -0
  544. data/lib/kumi/core/analyzer/state_serde.rb +4 -4
  545. data/lib/kumi/core/analyzer/structs/access_plan.rb +2 -2
  546. data/lib/kumi/core/analyzer/unsat_constant_evaluator.rb +59 -0
  547. data/lib/kumi/core/compiler/access_codegen.rb +1 -1
  548. data/lib/kumi/core/compiler/access_emit/base.rb +9 -5
  549. data/lib/kumi/core/compiler/access_emit/each_indexed.rb +10 -3
  550. data/lib/kumi/core/compiler/access_emit/materialize.rb +12 -5
  551. data/lib/kumi/core/compiler/access_emit/ravel.rb +10 -3
  552. data/lib/kumi/core/compiler/access_emit/read.rb +4 -1
  553. data/lib/kumi/core/compiler/access_planner.rb +42 -4
  554. data/lib/kumi/core/compiler/access_planner_v2.rb +164 -0
  555. data/lib/kumi/core/explain.rb +18 -11
  556. data/lib/kumi/core/functions/loader.rb +47 -0
  557. data/lib/kumi/core/functions/model.rb +10 -0
  558. data/lib/kumi/core/functions/type_rules.rb +108 -0
  559. data/lib/kumi/core/ir/execution_engine/interpreter.rb +1 -1
  560. data/lib/kumi/core/ir/execution_engine/profiler.rb +107 -97
  561. data/lib/kumi/core/ir.rb +6 -2
  562. data/lib/kumi/core/irv2/builder.rb +48 -0
  563. data/lib/kumi/core/irv2/declaration.rb +28 -0
  564. data/lib/kumi/core/irv2/module.rb +108 -0
  565. data/lib/kumi/core/irv2/value.rb +28 -0
  566. data/lib/kumi/core/lir/analyze.rb +64 -0
  567. data/lib/kumi/core/lir/build.rb +363 -0
  568. data/lib/kumi/core/lir/emit.rb +62 -0
  569. data/lib/kumi/core/lir/structs/instruction.rb +44 -0
  570. data/lib/kumi/core/lir/structs/literal.rb +14 -0
  571. data/lib/kumi/core/lir/structs/stamp.rb +13 -0
  572. data/lib/kumi/core/lir/support/error.rb +9 -0
  573. data/lib/kumi/core/lir/support/ids.rb +34 -0
  574. data/lib/kumi/core/lir/validate.rb +74 -0
  575. data/lib/kumi/core/lir.rb +34 -0
  576. data/lib/kumi/core/nast.rb +216 -0
  577. data/lib/kumi/core/ruby_parser/dsl.rb +2 -2
  578. data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +1 -1
  579. data/lib/kumi/core/ruby_parser/expression_converter.rb +10 -0
  580. data/lib/kumi/core/ruby_parser/input_builder.rb +16 -17
  581. data/lib/kumi/core/ruby_parser/schema_builder.rb +36 -10
  582. data/lib/kumi/core/ruby_parser/sugar.rb +64 -0
  583. data/lib/kumi/core/types/builder.rb +2 -2
  584. data/lib/kumi/core/types/normalizer.rb +2 -0
  585. data/lib/kumi/core/types/validator.rb +10 -3
  586. data/lib/kumi/core/types.rb +7 -0
  587. data/lib/kumi/dev/codegen.rb +194 -0
  588. data/lib/kumi/dev/golden/generator.rb +105 -0
  589. data/lib/kumi/dev/golden/reporter.rb +160 -0
  590. data/lib/kumi/dev/golden/representation.rb +45 -0
  591. data/lib/kumi/dev/golden/result.rb +98 -0
  592. data/lib/kumi/dev/golden/runtime_test.rb +93 -0
  593. data/lib/kumi/dev/golden/suite.rb +131 -0
  594. data/lib/kumi/dev/golden/verifier.rb +76 -0
  595. data/lib/kumi/dev/golden.rb +75 -0
  596. data/lib/kumi/dev/ir.rb +4 -4
  597. data/lib/kumi/dev/parse.rb +1 -1
  598. data/lib/kumi/dev/pretty_printer.rb +229 -0
  599. data/lib/kumi/dev/printer/irv2_formatter.rb +163 -0
  600. data/lib/kumi/dev/printer/width_aware_json.rb +44 -0
  601. data/lib/kumi/dev/profile_aggregator.rb +36 -38
  602. data/lib/kumi/dev/profile_runner.rb +19 -23
  603. data/lib/kumi/dev/runner.rb +12 -22
  604. data/lib/kumi/dev/support/kumi_runner.mjs +39 -0
  605. data/lib/kumi/dev.rb +3 -3
  606. data/lib/kumi/frontends/ruby.rb +12 -12
  607. data/lib/kumi/frontends/text.rb +26 -21
  608. data/lib/kumi/frontends.rb +6 -8
  609. data/lib/kumi/kernel_registry.rb +59 -0
  610. data/lib/kumi/pack/builder.rb +229 -0
  611. data/lib/kumi/pack.rb +15 -0
  612. data/lib/kumi/registry_v2/loader.rb +81 -0
  613. data/lib/kumi/registry_v2.rb +118 -0
  614. data/lib/kumi/schema.rb +83 -43
  615. data/lib/kumi/support/diff.rb +3 -2
  616. data/lib/kumi/support/ir_render.rb +1 -1
  617. data/lib/kumi/support/lir_printer.rb +143 -0
  618. data/lib/kumi/support/nast_printer.rb +93 -0
  619. data/lib/kumi/support/s_expression_printer.rb +5 -4
  620. data/lib/kumi/support/snast_printer.rb +111 -0
  621. data/lib/kumi/syntax/call_expression.rb +1 -1
  622. data/lib/kumi/syntax/input_declaration.rb +2 -2
  623. data/lib/kumi/syntax/node.rb +4 -12
  624. data/lib/kumi/syntax/root.rb +10 -0
  625. data/lib/kumi/syntax/trait_declaration.rb +1 -0
  626. data/lib/kumi/syntax/value_declaration.rb +1 -0
  627. data/lib/kumi/version.rb +1 -1
  628. data/lib/kumi.rb +47 -5
  629. metadata +571 -54
  630. data/docs/AST.md +0 -133
  631. data/docs/DSL.md +0 -154
  632. data/docs/FUNCTIONS.md +0 -176
  633. data/docs/VECTOR_SEMANTICS.md +0 -286
  634. data/docs/compiler_design_principles.md +0 -86
  635. data/docs/dev/analyzer-debug.md +0 -52
  636. data/docs/dev/parse-command.md +0 -64
  637. data/docs/dev/vm-profiling.md +0 -95
  638. data/docs/development/README.md +0 -120
  639. data/docs/development/error-reporting.md +0 -361
  640. data/docs/features/README.md +0 -58
  641. data/docs/features/analysis-type-inference.md +0 -42
  642. data/docs/features/analysis-unsat-detection.md +0 -71
  643. data/docs/features/hierarchical-broadcasting.md +0 -415
  644. data/docs/features/input-declaration-system.md +0 -58
  645. data/docs/features/performance.md +0 -14
  646. data/docs/features/s-expression-printer.md +0 -77
  647. data/docs/schema_metadata/broadcasts.md +0 -53
  648. data/docs/schema_metadata/cascades.md +0 -45
  649. data/docs/schema_metadata/declarations.md +0 -54
  650. data/docs/schema_metadata/dependencies.md +0 -57
  651. data/docs/schema_metadata/evaluation_order.md +0 -29
  652. data/docs/schema_metadata/examples.md +0 -95
  653. data/docs/schema_metadata/inferred_types.md +0 -46
  654. data/docs/schema_metadata/inputs.md +0 -86
  655. data/docs/schema_metadata.md +0 -108
  656. data/golden/mixed_nesting/schema.kumi +0 -42
  657. data/lib/kumi/core/function_registry/collection_functions.rb +0 -298
  658. data/lib/kumi/core/function_registry/comparison_functions.rb +0 -33
  659. data/lib/kumi/core/function_registry/conditional_functions.rb +0 -48
  660. data/lib/kumi/core/function_registry/function_builder.rb +0 -184
  661. data/lib/kumi/core/function_registry/logical_functions.rb +0 -214
  662. data/lib/kumi/core/function_registry/math_functions.rb +0 -74
  663. data/lib/kumi/core/function_registry/stat_functions.rb +0 -156
  664. data/lib/kumi/core/function_registry/string_functions.rb +0 -57
  665. data/lib/kumi/core/function_registry/type_functions.rb +0 -53
  666. data/lib/kumi/core/function_registry.rb +0 -176
  667. data/lib/kumi/registry.rb +0 -32
  668. data/lib/kumi/runtime/executable.rb +0 -135
  669. data/lib/kumi/runtime/run.rb +0 -105
  670. data/performance_results.txt +0 -63
  671. data/scripts/analyze_broadcast_methods.rb +0 -68
  672. data/scripts/analyze_cascade_methods.rb +0 -74
  673. data/scripts/check_broadcasting_coverage.rb +0 -51
  674. data/scripts/find_dead_code.rb +0 -114
  675. data/scripts/generate_function_docs.rb +0 -71
  676. data/scripts/test_mixed_nesting_performance.rb +0 -206
data/docs/SYNTAX.md CHANGED
@@ -1,511 +1,764 @@
1
- # Kumi DSL Syntax Reference
1
+ # Kumi Syntax — Quick Reference & Guide
2
2
 
3
- This document provides a comprehensive comparison of Kumi's DSL syntax showing both the sugar syntax (convenient, readable) and the underlying sugar-free syntax (explicit function calls).
3
+ ## Quick Reference
4
4
 
5
- ## Table of Contents
5
+ ### File Structure
6
+ ```kumi
7
+ schema do
8
+ input do
9
+ # Input shape declarations
10
+ end
11
+
12
+ # Declarations: let, value, trait
13
+ end
14
+ ```
15
+
16
+ ### Types
17
+ ```kumi
18
+ integer # Integer numbers
19
+ float # Floating point numbers
20
+ string # Text strings
21
+ array # Sequential collections
22
+ hash # Structured objects
23
+ ```
24
+
25
+ ### Declarations
26
+ ```kumi
27
+ let :name, expr # Intermediate value
28
+ value :name, expr # Output value
29
+ trait :name, expr # Boolean mask
30
+ ```
31
+
32
+ ### Operators
33
+
34
+ **Arithmetic:** `+` `-` `*` `/` `**` `%`
35
+ **Comparison:** `>` `>=` `<` `<=` `==` `!=`
36
+ **Boolean:** `&` (AND) `|` (OR)
37
+ **Indexing:** `tuple[0]` `tuple[1]` ...
38
+
39
+ ### Aggregation Functions
40
+
41
+ | Function | Description | Example |
42
+ |----------|-------------|---------|
43
+ | `fn(:sum, arr)` | Sum all elements | `fn(:sum, input.items.item.price)` |
44
+ | `fn(:count, arr)` | Count elements | `fn(:count, input.items.item.price)` |
45
+ | `fn(:max, arr)` | Maximum value | `fn(:max, input.items.item.price)` |
46
+ | `fn(:min, arr)` | Minimum value | `fn(:min, input.items.item.price)` |
47
+ | `fn(:mean, arr)` | Average (aliases: `avg`) | `fn(:mean, input.scores.score)` |
48
+ | `fn(:sum_if, vals, cond)` | Sum where condition is true | `fn(:sum_if, input.items.item.price, expensive)` |
49
+ | `fn(:count_if, vals, match)` | Count matching values | `fn(:count_if, input.cells.value, 0)` |
50
+ | `fn(:mean_if, vals, cond)` | Average where true (aliases: `avg_if`) | `fn(:mean_if, input.scores.score, passing)` |
51
+ | `fn(:any, arr)` | True if any element true | `fn(:any, input.flags.active)` |
52
+ | `fn(:all, arr)` | True if all elements true | `fn(:all, input.checks.passed)` |
53
+ | `fn(:join, arr)` | Join strings | `fn(:join, input.words.word)` |
54
+
55
+ ### Elementwise Functions
56
+
57
+ **Arithmetic:**
58
+ - `fn(:abs, x)` — Absolute value
59
+ - `fn(:clamp, x, lo, hi)` — Clamp to range
60
+
61
+ **String:**
62
+ - `fn(:concat, s1, s2)` — Concatenate strings
63
+ - `fn(:upcase, str)` — Convert to uppercase
64
+ - `fn(:downcase, str)` — Convert to lowercase
65
+ - `fn(:length, str)` — String length (aliases: `len`, `size`)
66
+
67
+ **Array:**
68
+ - `fn(:array_size, arr)` — Array length (alias: `size`)
69
+ - `fn(:at, arr, idx)` — Get element at index (alias: `[]`)
70
+
71
+ **Hash:**
72
+ - `fn(:fetch, key)` — Fetch value from hash
73
+
74
+ ### Control Flow
75
+ ```kumi
76
+ # Simple selection
77
+ select(condition, if_true, if_false)
78
+
79
+ # Multi-way cascade (first match wins)
80
+ value :result do
81
+ on cond1, cond2, expr1 # If cond1 AND cond2
82
+ on cond3, expr2 # Else if cond3
83
+ base expr3 # Else (default)
84
+ end
85
+ ```
86
+
87
+ ### Spatial Operations
88
+ ```kumi
89
+ # Shift — access neighbors
90
+ shift(expr, offset, axis_offset: 0, policy: :zero)
91
+ # offset: -N (left/up), +N (right/down)
92
+ # axis_offset: 0 (innermost/x), 1 (next/y)
93
+ # policy: :zero (default) | :wrap | :clamp
94
+
95
+ # Roll — rotate with wrapping
96
+ roll(expr, offset, policy: :wrap)
97
+ # policy: :wrap (default) | :clamp
98
+
99
+ # Index access
100
+ index(:name) # Get index value (requires array declared with index: :name)
101
+ ```
102
+
103
+ ### Common Patterns
104
+
105
+ **Filter and aggregate:**
106
+ ```kumi
107
+ trait :expensive, input.items.item.price > 100.0
108
+ value :expensive_total, fn(:sum_if, input.items.item.price, expensive)
109
+ ```
110
+
111
+ **Map then reduce:**
112
+ ```kumi
113
+ value :subtotals, input.items.item.price * input.items.item.quantity
114
+ value :total, fn(:sum, subtotals)
115
+ ```
6
116
 
7
- - [Schema Structure](#schema-structure)
8
- - [Input Declarations](#input-declarations)
9
- - [Value Declarations](#value-declarations)
10
- - [Trait Declarations](#trait-declarations)
11
- - [Expressions](#expressions)
12
- - [Functions](#functions)
13
- - [Array Broadcasting](#array-broadcasting)
14
- - [Cascade Logic](#cascade-logic)
15
- - [References](#references)
117
+ **Broadcasting (parent to child):**
118
+ ```kumi
119
+ value :dept_total, fn(:sum, input.depts.dept.teams.team.headcount)
120
+ trait :large_team, input.depts.dept.teams.team.headcount > dept_total / 3
121
+ ```
122
+
123
+ **Index-based calculation:**
124
+ ```kumi
125
+ let :W, fn(:array_size, input.x.y)
126
+ value :row_major, (index(:i) * W) + index(:j)
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Detailed Guide
132
+
133
+ ### 1) Input Shapes
134
+
135
+ #### Scalars
136
+
137
+ Scalar inputs represent single values:
138
+
139
+ ```kumi
140
+ input do
141
+ integer :x
142
+ float :rate
143
+ string :name
144
+ end
145
+ ```
16
146
 
17
- ## Schema Structure
147
+ **Example:**
148
+ ```kumi
149
+ schema do
150
+ input do
151
+ integer :x
152
+ integer :y
153
+ end
154
+
155
+ value :sum, input.x + input.y
156
+ value :product, input.x * input.y
157
+ end
158
+ ```
18
159
 
19
- ### Basic Schema Template
160
+ #### Arrays
20
161
 
21
- ```ruby
22
- # With Sugar (Recommended)
23
- module MySchema
24
- extend Kumi::Schema
162
+ Arrays represent sequences. Navigate using dot notation through each level.
25
163
 
26
- schema do
27
- input do
28
- # Input field declarations
164
+ **1D Array:**
165
+ ```kumi
166
+ input do
167
+ array :cells do
168
+ integer :value # Access: input.cells.value
169
+ end
170
+ end
171
+ ```
172
+
173
+ **2D Array (grid):**
174
+ ```kumi
175
+ input do
176
+ array :rows do
177
+ array :col do
178
+ integer :v # Access: input.rows.col.v
29
179
  end
180
+ end
181
+ end
182
+ ```
30
183
 
31
- # Traits and values using sugar syntax
184
+ **3D Array (cube):**
185
+ ```kumi
186
+ input do
187
+ array :cube do
188
+ array :layer do
189
+ array :row do
190
+ integer :cell # Access: input.cube.layer.row.cell
191
+ end
192
+ end
32
193
  end
33
194
  end
195
+ ```
196
+
197
+ #### Arrays of Hashes
34
198
 
35
- # Sugar-Free (Explicit)
36
- module MySchema
37
- extend Kumi::Schema
199
+ Common pattern for structured collections:
38
200
 
39
- schema do
40
- input do
41
- # Input field declarations (same)
201
+ ```kumi
202
+ input do
203
+ array :items do
204
+ hash :item do
205
+ float :price
206
+ integer :quantity
207
+ string :category
42
208
  end
209
+ end
210
+ end
211
+
212
+ # Access: input.items.item.price
213
+ # input.items.item.quantity
214
+ ```
215
+
216
+ #### Hashes
217
+
218
+ Hashes represent structured data with named fields:
43
219
 
44
- # Traits and values using explicit function calls
220
+ ```kumi
221
+ input do
222
+ hash :config do
223
+ string :app_name
224
+ array :servers do
225
+ hash :server do
226
+ string :hostname
227
+ integer :port
228
+ end
229
+ end
45
230
  end
46
231
  end
232
+
233
+ # Access scalar: input.config.app_name
234
+ # Access nested: input.config.servers.server.hostname
47
235
  ```
48
236
 
49
- ## Input Declarations
237
+ #### Arrays with Named Indices
50
238
 
51
- Input declarations are the same in both syntaxes:
239
+ Declare indices to access position values:
52
240
 
53
- ```ruby
241
+ ```kumi
54
242
  input do
55
- # Type-specific declarations
56
- integer :age, domain: 18..65
57
- string :status, domain: %w[active inactive suspended]
58
- float :score, domain: 0.0..100.0
59
- array :tags, elem: { type: :string }
60
- hash :metadata, key: { type: :string }, val: { type: :any }
61
-
62
- # Untyped fields
63
- any :misc_data
243
+ array :x, index: :i do
244
+ array :y, index: :j do
245
+ integer :_ # Placeholder (value unused)
246
+ end
247
+ end
64
248
  end
249
+
250
+ # Use in expressions
251
+ let :W, fn(:array_size, input.x.y)
252
+ value :row_major, (index(:i) * W) + index(:j)
253
+ value :col_major, (index(:j) * fn(:array_size, input.x)) + index(:i)
65
254
  ```
66
255
 
67
- ## Value Declarations
256
+ ### 2) Declarations
68
257
 
69
- ### Arithmetic Operations
258
+ #### `let` — Intermediate Values
70
259
 
71
- ```ruby
72
- # With Sugar
73
- value :total_score, input.math_score + input.verbal_score + input.writing_score
74
- value :average_score, total_score / 3
75
- value :scaled_score, average_score * 1.5
76
- value :final_score, scaled_score - input.penalty_points
260
+ Use for computed values referenced elsewhere:
77
261
 
78
- # Sugar-Free
79
- value :total_score, fn(:add, fn(:add, input.math_score, input.verbal_score), input.writing_score)
80
- value :average_score, fn(:divide, total_score, 3)
81
- value :scaled_score, fn(:multiply, average_score, 1.5)
82
- value :final_score, fn(:subtract, scaled_score, input.penalty_points)
262
+ ```kumi
263
+ let :x_sq, input.x * input.x
264
+ let :y_sq, input.y * input.y
265
+ let :distance_sq, x_sq + y_sq
266
+ value :distance, distance_sq ** 0.5
83
267
  ```
84
268
 
85
- ### Mathematical Functions
269
+ #### `value` — Outputs
86
270
 
87
- ```ruby
88
- # With Sugar (Note: Some functions require sugar-free syntax)
89
- value :score_variance, fn(:power, fn(:subtract, input.score, average_score), 2)
90
- value :max_possible, fn(:max, [input.math_score, input.verbal_score, input.writing_score])
91
- value :min_score, fn(:min, [input.math_score, input.verbal_score])
271
+ Results serialized to output:
92
272
 
93
- # Sugar-Free
94
- value :score_variance, fn(:power, fn(:subtract, input.score, average_score), 2)
95
- value :max_possible, fn(:max, [input.math_score, input.verbal_score, input.writing_score])
96
- value :min_score, fn(:min, [input.math_score, input.verbal_score])
273
+ ```kumi
274
+ value :cart_total, fn(:sum, input.items.item.price * input.items.item.quantity)
275
+ value :item_count, fn(:count, input.items.item.quantity)
97
276
  ```
98
277
 
99
- ## Trait Declarations
278
+ #### `trait` — Boolean Masks
100
279
 
101
- ### Comparison Operations
280
+ Boolean conditions for filtering/branching:
102
281
 
103
- ```ruby
104
- # With Sugar
105
- trait :high_scorer, input.total_score >= 1400
106
- trait :perfect_math, input.math_score == 800
107
- trait :needs_improvement, input.total_score < 1000
108
- trait :above_average, input.average_score > 500
282
+ ```kumi
283
+ trait :expensive_items, input.items.item.price > 100.0
284
+ trait :electronics, input.items.item.category == "electronics"
285
+ trait :high_value, expensive_items & electronics
109
286
 
110
- # Sugar-Free
111
- trait :high_scorer, fn(:>=, input.total_score, 1400)
112
- trait :perfect_math, fn(:==, input.math_score, 800)
113
- trait :needs_improvement, fn(:<, input.total_score, 1000)
114
- trait :above_average, fn(:>, input.average_score, 500)
287
+ value :discounted, select(high_value,
288
+ input.items.item.price * 0.8,
289
+ input.items.item.price
290
+ )
115
291
  ```
116
292
 
117
- ### Logical Operations
293
+ ### 3) Operators
118
294
 
119
- ```ruby
120
- # With Sugar
121
- trait :excellent_student, high_scorer & perfect_math
122
- trait :qualified, (input.age >= 18) & (input.score >= 1200) & (input.status == "active")
123
- trait :needs_review, needs_improvement & (input.attempts > 2)
295
+ **Arithmetic:**
296
+ ```kumi
297
+ + - * / ** %
124
298
 
125
- # Sugar-Free
126
- trait :excellent_student, fn(:and, high_scorer, perfect_math)
127
- trait :qualified, fn(:and, fn(:and, fn(:>=, input.age, 18), fn(:>=, input.score, 1200)), fn(:==, input.status, "active"))
128
- trait :needs_review, fn(:and, needs_improvement, fn(:>, input.attempts, 2))
299
+ value :total, input.x + input.y
300
+ value :area, input.width * input.height
301
+ value :power, input.base ** input.exponent
302
+ value :remainder, input.x % input.y
129
303
  ```
130
304
 
131
- ### String Operations
305
+ **Comparison:**
306
+ ```kumi
307
+ > >= < <= == !=
132
308
 
133
- ```ruby
134
- # All string operations use function syntax
135
- trait :long_name, fn(:string_length, input.name) > 20
136
- trait :starts_with_a, fn(:start_with?, input.name, "A")
137
- trait :contains_space, fn(:contains?, input.name, " ")
309
+ trait :is_adult, input.age >= 18
310
+ trait :is_expensive, input.price > 100.0
311
+ trait :exact_match, input.category == "electronics"
138
312
  ```
139
313
 
140
- ## Expressions
314
+ **Boolean:**
315
+ ```kumi
316
+ & | !
141
317
 
142
- ### Complex Expressions
318
+ trait :premium, is_adult & is_expensive
319
+ trait :eligible, is_member | is_trial
320
+ trait :not_active, !is_active
321
+ ```
143
322
 
144
- ```ruby
145
- # With Sugar
146
- value :weighted_score, (input.math_score * 0.4) + (input.verbal_score * 0.3) + (input.writing_score * 0.3)
147
- value :percentile_rank, ((scored_better_than / total_students) * 100).round(2)
323
+ ### 4) Functions
148
324
 
149
- # Sugar-Free
150
- value :weighted_score, fn(:add,
151
- fn(:add,
152
- fn(:multiply, input.math_score, 0.4),
153
- fn(:multiply, input.verbal_score, 0.3)
154
- ),
155
- fn(:multiply, input.writing_score, 0.3)
156
- )
157
- value :percentile_rank, fn(:round,
158
- fn(:multiply,
159
- fn(:divide, scored_better_than, total_students),
160
- 100
161
- ),
162
- 2
163
- )
325
+ All functions use `fn(:name, args...)` syntax.
326
+
327
+ #### Aggregation (Reduce Dimension)
328
+
329
+ **Sum and Count:**
330
+ ```kumi
331
+ value :total, fn(:sum, input.items.item.price)
332
+ value :count, fn(:count, input.items.item.price)
164
333
  ```
165
334
 
166
- ### Collection Operations
335
+ **Min, Max, Mean:**
336
+ ```kumi
337
+ value :highest, fn(:max, input.items.item.price)
338
+ value :lowest, fn(:min, input.items.item.price)
339
+ value :average, fn(:mean, input.scores.score)
340
+ ```
167
341
 
168
- ```ruby
169
- # With Sugar
170
- value :total_scores, input.score_array.sum
171
- value :score_count, input.score_array.size
172
- value :unique_scores, input.score_array.uniq.size
173
- value :sorted_scores, input.score_array.sort
342
+ **Conditional Aggregation:**
343
+ ```kumi
344
+ trait :expensive, input.items.item.price > 100.0
345
+ value :expensive_sum, fn(:sum_if, input.items.item.price, expensive)
346
+ value :expensive_avg, fn(:mean_if, input.items.item.price, expensive)
347
+ value :zero_count, fn(:count_if, input.cells.value, 0)
348
+ ```
174
349
 
175
- # Sugar-Free
176
- value :total_scores, fn(:sum, input.score_array)
177
- value :score_count, fn(:size, input.score_array)
178
- value :unique_scores, fn(:size, fn(:unique, input.score_array))
179
- value :sorted_scores, fn(:sort, input.score_array)
350
+ **Boolean Aggregation:**
351
+ ```kumi
352
+ value :has_any_active, fn(:any, input.flags.active)
353
+ value :all_passed, fn(:all, input.checks.passed)
180
354
  ```
181
355
 
182
- ## Functions
356
+ **String Aggregation:**
357
+ ```kumi
358
+ value :combined, fn(:join, input.words.word)
359
+ ```
183
360
 
184
- ### Built-in Functions Available
361
+ #### Elementwise (No Dimension Change)
185
362
 
186
- See [FUNCTIONS.md](FUNCTIONS.md)
363
+ **Array Utilities:**
364
+ ```kumi
365
+ value :num_rows, fn(:array_size, input.matrix.row)
366
+ value :first_item, fn(:at, input.items, 0)
187
367
 
188
- | Category | Sugar | Sugar-Free |
189
- |----------|-------|------------|
190
- | **Arithmetic** | `+`, `-`, `*`, `/`, `**` | `fn(:add, a, b)`, `fn(:subtract, a, b)`, etc. |
191
- | **Comparison** | `>`, `<`, `>=`, `<=`, `==`, `!=` | `fn(:>, a, b)`, `fn(:<, a, b)`, etc. |
192
- | **Logical** | `&` `|` | `fn(:and, a, b)`, `fn(:or, a, b)`, `fn(:not, a)` |
193
- | **Math** | `abs`, `round`, `ceil`, `floor` | `fn(:abs, x)`, `fn(:round, x)`, etc. |
194
- | **String** | `.length`, `.upcase`, `.downcase` | `fn(:string_length, s)`, `fn(:upcase, s)`, etc. |
195
- | **Collection** | `.sum`, `.size`, `.max`, `.min` | `fn(:sum, arr)`, `fn(:size, arr)`, etc. |
368
+ let :W, fn(:array_size, input.x.y)
369
+ value :linear_idx, (index(:i) * W) + index(:j)
370
+ ```
371
+
372
+ **String Operations:**
373
+ ```kumi
374
+ value :full_name, fn(:concat, input.first_name, input.last_name)
375
+ value :upper, fn(:upcase, input.name)
376
+ value :lower, fn(:downcase, input.name)
377
+ value :name_len, fn(:length, input.name)
378
+ ```
379
+
380
+ **Math:**
381
+ ```kumi
382
+ value :magnitude, fn(:abs, input.value)
383
+ value :bounded, fn(:clamp, input.value, 0, 100)
384
+ ```
196
385
 
197
- ### Custom Function Calls
386
+ ### 5) Conditionals
198
387
 
199
- ```ruby
200
- # With Sugar (when available)
201
- value :clamped_score, input.raw_score.clamp(0, 1600)
202
- value :formatted_name, input.first_name + " " + input.last_name
388
+ #### Simple Selection with `select`
203
389
 
204
- # Sugar-Free (always available)
205
- value :clamped_score, fn(:clamp, input.raw_score, 0, 1600)
206
- value :formatted_name, fn(:add, fn(:add, input.first_name, " "), input.last_name)
390
+ ```kumi
391
+ trait :is_expensive, input.items.item.price > 100.0
392
+ value :discounted, select(is_expensive,
393
+ input.items.item.price * 0.9,
394
+ input.items.item.price
395
+ )
207
396
  ```
208
397
 
209
- ## Array Broadcasting
398
+ #### Multi-way Cascade with `on`
210
399
 
211
- Array broadcasting enables element-wise operations on array fields with automatic vectorization.
400
+ First matching condition wins:
212
401
 
213
- ### Array Input Declarations
402
+ ```kumi
403
+ trait :x_positive, input.x > 0
404
+ trait :y_positive, input.y > 0
214
405
 
215
- ```ruby
216
- input do
217
- # Structured array with defined fields
218
- array :line_items do
219
- float :price
220
- integer :quantity
221
- string :category
222
- end
223
-
224
- # Nested arrays with hash objects
225
- array :orders do
226
- array :items do
227
- hash :product do
228
- string :name
229
- float :base_price
230
- end
231
- integer :quantity
232
- end
233
- end
234
-
235
- # Dynamic arrays with flexible element types
236
- array :api_responses do
237
- element :any, :response_data # For dynamic/unknown hash structures
238
- end
239
-
240
- array :measurements do
241
- element :float, :value # For simple scalar arrays
242
- end
406
+ value :status do
407
+ on y_positive, x_positive, "both positive"
408
+ on x_positive, "x positive"
409
+ on y_positive, "y positive"
410
+ base "neither positive"
243
411
  end
244
412
  ```
245
413
 
246
- ### Element-wise Operations
414
+ **Complex Example with Broadcasting:**
415
+ ```kumi
416
+ trait :high_performer, input.employees.employee.rating >= 4.5
417
+ trait :senior, input.employees.employee.level == "senior"
418
+ trait :top_team, input.teams.team.performance_score >= 0.9
247
419
 
248
- ```ruby
249
- # With Sugar - Automatic Broadcasting
250
- value :subtotals, input.line_items.price * input.line_items.quantity
251
- trait :is_taxable, (input.line_items.category != "digital")
252
- value :discounted_prices, input.line_items.price * 0.9
253
-
254
- # Sugar-Free - Explicit Broadcasting
255
- value :subtotals, fn(:multiply, input.line_items.price, input.line_items.quantity)
256
- trait :is_taxable, fn(:!=, input.line_items.category, "digital")
257
- value :discounted_prices, fn(:multiply, input.line_items.price, 0.9)
420
+ value :bonus do
421
+ on high_performer, senior, top_team, input.employees.employee.salary * 0.30
422
+ on high_performer, top_team, input.employees.employee.salary * 0.20
423
+ base input.employees.employee.salary * 0.05
424
+ end
258
425
  ```
259
426
 
260
- ### Aggregation Operations
427
+ ### 6) Tuples and Indexing
261
428
 
262
- ```ruby
263
- # With Sugar - Automatic Aggregation Detection
264
- value :total_subtotal, fn(:sum, subtotals)
265
- value :avg_price, fn(:avg, input.line_items.price)
266
- value :max_quantity, fn(:max, input.line_items.quantity)
267
- value :item_count, fn(:size, input.line_items)
429
+ #### Tuple Literals
268
430
 
269
- # Sugar-Free - Same Syntax
270
- value :total_subtotal, fn(:sum, subtotals)
271
- value :avg_price, fn(:avg, input.line_items.price)
272
- value :max_quantity, fn(:max, input.line_items.quantity)
273
- value :item_count, fn(:size, input.line_items)
431
+ ```kumi
432
+ value :scores, [100, 85, 92]
433
+ value :coords, [input.x, input.y]
434
+ value :mixed, [1, input.x + 10, input.y * 2]
274
435
  ```
275
436
 
276
- ### Nested Array Access
437
+ #### Tuple Indexing
277
438
 
278
- ```ruby
279
- # With Sugar - Deep Field Access
280
- value :all_product_names, input.orders.items.product.name
281
- value :total_values, input.orders.items.product.base_price * input.orders.items.quantity
439
+ ```kumi
440
+ value :scores, [100, 85, 92]
441
+ value :first, scores[0]
442
+ value :second, scores[1]
443
+ value :third, scores[2]
444
+ ```
282
445
 
283
- # Sugar-Free - Same Deep Access
284
- value :all_product_names, input.orders.items.product.name
285
- value :total_values, fn(:multiply, input.orders.items.product.base_price, input.orders.items.quantity)
446
+ #### Operations on Tuples
447
+
448
+ ```kumi
449
+ value :coords, [input.x, input.y, input.z]
450
+ value :max_coord, fn(:max, coords)
451
+ value :sum_coords, fn(:sum, coords)
286
452
  ```
287
453
 
288
- ### Mixed Operations
454
+ #### Vectorized Tuple Operations
455
+
456
+ When tuples contain array elements:
289
457
 
290
- ```ruby
291
- # With Sugar - Element-wise then Aggregation
292
- value :line_totals, input.items.price * input.items.quantity
293
- value :order_total, fn(:sum, line_totals)
294
- value :avg_line_total, fn(:avg, line_totals)
295
- trait :has_expensive, fn(:any?, expensive_items)
458
+ ```kumi
459
+ trait :x_large, input.points.point.x > 100
460
+ value :selected, select(x_large,
461
+ input.points.point.x,
462
+ input.points.point.y
463
+ )
296
464
 
297
- # Sugar-Free - Same Pattern
298
- value :line_totals, fn(:multiply, input.items.price, input.items.quantity)
299
- value :order_total, fn(:sum, line_totals)
300
- value :avg_line_total, fn(:avg, line_totals)
301
- trait :has_expensive, fn(:any?, expensive_items)
465
+ # For each point, compute max of selected and x
466
+ value :max_per_point, fn(:max, [selected, input.points.point.x])
302
467
  ```
303
468
 
304
- ### Dynamic Hash Elements with `element :any`
469
+ ### 7) Spatial Operations
470
+
471
+ #### `shift` — Access Neighbors
472
+
473
+ Move along arrays to access adjacent values.
474
+
475
+ **Syntax:**
476
+ ```kumi
477
+ shift(expr, offset, axis_offset: 0, policy: :zero)
478
+ ```
305
479
 
306
- For arrays containing hash data with unknown or flexible structure, use `element :any` instead of defining explicit hash objects:
480
+ **Parameters:**
481
+ - `offset`: Distance to shift (negative = left/up, positive = right/down)
482
+ - `axis_offset`: Which dimension (0 = innermost/x, 1 = next/y, etc.)
483
+ - `policy`: Edge handling
484
+ - `:zero` (default) — Use 0 for out-of-bounds
485
+ - `:wrap` — Wrap to opposite edge
486
+ - `:clamp` — Repeat edge value
307
487
 
308
- ```ruby
488
+ **1D Example:**
489
+ ```kumi
309
490
  input do
310
- array :api_responses do
311
- element :any, :response_data
312
- end
313
-
314
- array :user_profiles do
315
- element :any, :profile_info
491
+ array :cells do
492
+ integer :value
316
493
  end
317
494
  end
318
495
 
319
- # Access hash data using fn(:fetch)
320
- value :response_codes, fn(:fetch, input.api_responses.response_data, "status")
321
- value :user_names, fn(:fetch, input.user_profiles.profile_info, "name")
322
- value :user_ages, fn(:fetch, input.user_profiles.profile_info, "age")
496
+ value :left, shift(input.cells.value, -1)
497
+ value :right, shift(input.cells.value, 1, policy: :wrap)
498
+ ```
499
+
500
+ **2D Example (Game of Life):**
501
+ ```kumi
502
+ let :a, input.rows.col.alive
503
+
504
+ # Horizontal (axis_offset: 0, default)
505
+ let :w, shift(a, -1) # West
506
+ let :e, shift(a, 1) # East
507
+
508
+ # Vertical (axis_offset: 1)
509
+ let :n, shift(a, -1, axis_offset: 1) # North
510
+ let :s, shift(a, 1, axis_offset: 1) # South
323
511
 
324
- # Mathematical operations on extracted values
325
- value :avg_response_time, fn(:mean, fn(:fetch, input.api_responses.response_data, "response_time"))
326
- value :total_users, fn(:size, input.user_profiles.profile_info)
512
+ # Diagonals (shift twice)
513
+ let :nw, shift(n, -1)
514
+ let :ne, shift(n, 1)
515
+ let :sw, shift(s, -1)
516
+ let :se, shift(s, 1)
327
517
 
328
- # Traits using dynamic data
329
- trait :success_responses, fn(:any?, fn(:fetch, input.api_responses.response_data, "status") == 200)
330
- trait :adult_users, fn(:any?, fn(:fetch, input.user_profiles.profile_info, "age") >= 18)
518
+ let :neighbors, fn(:sum, [n, s, w, e, nw, ne, sw, se])
331
519
  ```
332
520
 
333
- **Use Cases for `element :any`:**
334
- - API responses with varying schemas
335
- - Configuration data with flexible structure
336
- - Dynamic hash structures (unknown keys at schema definition time)
337
- - Legacy data where hash structure may vary
338
- - When you need maximum flexibility without type constraints
521
+ #### `roll` Rotate with Wrapping
339
522
 
340
- **Comparison: `element :any` vs Hash Objects**
523
+ Convenience for 1D rotations:
341
524
 
342
- ```ruby
343
- # element :any approach (flexible, dynamic)
344
- array :users do
345
- element :any, :data
346
- end
347
- value :names, fn(:fetch, input.users.data, "name")
525
+ ```kumi
526
+ value :roll_right, roll(input.cells.value, 1) # Wrap (default)
527
+ value :roll_left, roll(input.cells.value, -1)
528
+ value :roll_clamp, roll(input.cells.value, 1, policy: :clamp)
529
+ ```
348
530
 
349
- # hash object approach (typed, structured)
350
- array :users do
351
- hash :data do
352
- string :name
353
- integer :age
354
- end
355
- end
356
- value :names, input.users.data.name
531
+ ### 8) Reductions and Broadcasting
532
+
533
+ #### Reductions
534
+
535
+ Aggregation functions reduce dimensionality:
536
+
537
+ **1D → Scalar:**
538
+ ```kumi
539
+ value :total, fn(:sum, input.items.item.price)
357
540
  ```
358
541
 
359
- ### Broadcasting Type Inference
542
+ **2D 1D (reduce inner dimension):**
543
+ ```kumi
544
+ value :row_sums, fn(:sum, input.rows.col.v)
545
+ ```
546
+
547
+ **2D → Scalar (double reduction):**
548
+ ```kumi
549
+ value :grand_total, fn(:sum, fn(:sum, input.rows.col.v))
550
+ ```
551
+
552
+ **3D → Scalar (triple reduction):**
553
+ ```kumi
554
+ trait :over_limit, input.cube.layer.row.cell > 100
555
+ value :sum_over, fn(:sum_if, input.cube.layer.row.cell, over_limit)
556
+ value :total, fn(:sum, fn(:sum, sum_over))
557
+ ```
558
+
559
+ #### Broadcasting
560
+
561
+ Values at higher/parent levels automatically broadcast to lower/child levels.
360
562
 
361
- The type system automatically infers appropriate types:
362
- - `input.items.price` (float array) → inferred as `:float` per element
363
- - `input.items.price * input.items.quantity` → element-wise `:float` result
364
- - `fn(:sum, input.items.price)` → scalar `:float` result
563
+ **Scalar to Array:**
564
+ ```kumi
565
+ input do
566
+ array :items do
567
+ hash :item do
568
+ float :price
569
+ end
570
+ end
571
+ float :discount # Scalar
572
+ end
365
573
 
366
- ## Cascade Logic
574
+ # discount broadcasts to each item
575
+ value :discounted, input.items.item.price * (1.0 - input.discount)
576
+ ```
367
577
 
368
- Cascades are similar to Ruby when case, where each case is one of more trait reference and finally the value if that branch is true.
369
- ```ruby
370
- value :grade_letter do
371
- on excellent_student, "A+"
372
- on high_scorer, "A"
373
- on above_average, "B"
374
- on needs_improvement, "C"
375
- base "F"
578
+ **Parent Level to Child Level:**
579
+ ```kumi
580
+ input do
581
+ array :departments do
582
+ hash :dept do
583
+ array :teams do
584
+ hash :team do
585
+ integer :headcount
586
+ end
587
+ end
588
+ end
589
+ end
376
590
  end
591
+
592
+ # Reduce to department level
593
+ value :dept_total, fn(:sum, input.departments.dept.teams.team.headcount)
594
+
595
+ # dept_total broadcasts to team level
596
+ trait :large_team, input.departments.dept.teams.team.headcount > dept_total / 3
377
597
  ```
378
598
 
599
+ **Key Rule:** Axes align by identity (lineage), not name. A department-level value knows which teams belong to it.
600
+
601
+ ### 9) Common Patterns
379
602
 
380
- ## References
603
+ #### Filter and Aggregate
381
604
 
382
- ### Referencing Other Declarations
605
+ ```kumi
606
+ trait :expensive, input.items.item.price > 100.0
607
+ value :expensive_total, fn(:sum_if, input.items.item.price, expensive)
608
+ value :expensive_count, fn(:sum_if, 1, expensive)
609
+ ```
383
610
 
384
- ```ruby
385
- # Both syntaxes (same)
386
- trait :qualified_senior, qualified & (input.age >= 65)
387
- value :bonus_points, qualified_senior ? 100 : 0
611
+ #### Map then Reduce
388
612
 
389
- # Explicit reference syntax (both syntaxes)
390
- trait :qualified_senior, ref(:qualified) & (input.age >= 65)
391
- value :bonus_points, ref(:qualified_senior) ? 100 : 0
613
+ ```kumi
614
+ value :subtotals, input.items.item.price * input.items.item.quantity
615
+ value :cart_total, fn(:sum, subtotals)
392
616
  ```
393
617
 
394
- ### Input Field References
618
+ #### Conditional Aggregation in Hierarchies
395
619
 
396
- ```ruby
397
- # Both syntaxes (same)
398
- input.field_name # Access input field
399
- input.field_name.method # Call method on input field (sugar)
400
- fn(:method, input.field_name) # Call method on input field (sugar-free)
620
+ ```kumi
621
+ trait :over_limit, input.cube.layer.row.cell > 100
622
+ value :cell_sum, fn(:sum_if, input.cube.layer.row.cell, over_limit)
623
+ value :total, fn(:sum, fn(:sum, cell_sum))
401
624
  ```
402
625
 
403
- ## Complete Example Comparison
626
+ #### Hash Construction
404
627
 
405
- ### With Sugar (Recommended)
628
+ ```kumi
629
+ value :users, {
630
+ name: input.users.user.name,
631
+ state: input.users.user.state
632
+ }
406
633
 
407
- ```ruby
408
- module StudentEvaluation
409
- extend Kumi::Schema
634
+ trait :is_john, input.users.user.name == "John"
635
+ value :john_user, select(is_john, users, "NOT_JOHN")
636
+ ```
410
637
 
411
- schema do
412
- input do
413
- integer :math_score, domain: 0..800
414
- integer :verbal_score, domain: 0..800
415
- integer :writing_score, domain: 0..800
416
- integer :age, domain: 16..25
417
- string :status, domain: %w[active inactive]
418
- end
638
+ #### Index-Based Calculations
419
639
 
420
- # Calculated values with sugar
421
- value :total_score, input.math_score + input.verbal_score + input.writing_score
422
- value :average_score, total_score / 3
423
- value :scaled_average, fn(:round, average_score * 1.2, 2)
424
-
425
- # Traits with sugar
426
- trait :high_performer, total_score >= 2100
427
- trait :math_excellence, input.math_score >= 750
428
- trait :eligible_student, (input.age >= 18) & (input.status == "active")
429
- trait :scholarship_candidate, high_performer & math_excellence & eligible_student
430
-
431
- # Cascade with sugar-defined traits
432
- value :scholarship_amount do
433
- on scholarship_candidate, 10000
434
- on high_performer, 5000
435
- on math_excellence, 2500
436
- base 0
640
+ ```kumi
641
+ input do
642
+ array :x, index: :i do
643
+ array :y, index: :j do
644
+ integer :_
437
645
  end
438
646
  end
439
647
  end
648
+
649
+ let :W, fn(:array_size, input.x.y)
650
+ value :row_major, (index(:i) * W) + index(:j)
651
+ value :col_major, (index(:j) * fn(:array_size, input.x)) + index(:i)
652
+ value :coord_sum, index(:i) + index(:j)
440
653
  ```
441
654
 
442
- ### Sugar-Free (Explicit)
655
+ ---
443
656
 
444
- ```ruby
445
- module StudentEvaluation
446
- extend Kumi::Schema
657
+ ## Complete Examples
447
658
 
448
- schema do
449
- input do
450
- integer :math_score, domain: 0..800
451
- integer :verbal_score, domain: 0..800
452
- integer :writing_score, domain: 0..800
453
- integer :age, domain: 16..25
454
- string :status, domain: %w[active inactive]
455
- end
659
+ ### Shopping Cart with Discounts
456
660
 
457
- # Calculated values without sugar
458
- value :total_score, fn(:add, fn(:add, input.math_score, input.verbal_score), input.writing_score)
459
- value :average_score, fn(:divide, total_score, 3)
460
- value :scaled_average, fn(:round, fn(:multiply, average_score, 1.2), 2)
461
-
462
- # Traits without sugar
463
- trait :high_performer, fn(:>=, total_score, 2100)
464
- trait :math_excellence, fn(:>=, input.math_score, 750)
465
- trait :eligible_student, fn(:and, fn(:>=, input.age, 18), fn(:==, input.status, "active"))
466
- trait :scholarship_candidate, fn(:and, fn(:and, high_performer, math_excellence), eligible_student)
467
-
468
- # Cascade with sugar-free defined traits
469
- value :scholarship_amount do
470
- on scholarship_candidate, 10000
471
- on high_performer, 5000
472
- on math_excellence, 2500
473
- base 0
661
+ ```kumi
662
+ schema do
663
+ input do
664
+ array :items do
665
+ hash :item do
666
+ float :price
667
+ integer :qty
668
+ end
474
669
  end
670
+ float :discount
475
671
  end
672
+
673
+ value :items_subtotal, input.items.item.price * input.items.item.qty
674
+ value :items_discounted, input.items.item.price * (1.0 - input.discount)
675
+
676
+ value :items_is_big, input.items.item.price > 100.0
677
+ value :items_effective, select(items_is_big,
678
+ items_subtotal * 0.9,
679
+ items_subtotal
680
+ )
681
+
682
+ value :total_qty, fn(:sum, input.items.item.qty)
683
+ value :cart_total, fn(:sum, items_subtotal)
684
+ value :cart_total_effective, fn(:sum, items_effective)
476
685
  end
477
686
  ```
478
687
 
479
- ## When to Use Each Syntax
688
+ ### Conway's Game of Life
689
+
690
+ ```kumi
691
+ schema do
692
+ input do
693
+ array :rows do
694
+ array :col do
695
+ integer :alive # 0 or 1
696
+ end
697
+ end
698
+ end
699
+
700
+ let :a, input.rows.col.alive
480
701
 
481
- ### Use Sugar Syntax When:
482
- - Writing schemas by hand
483
- - Readability is important
484
- - ✅ Working with simple to moderate complexity
485
- - You want concise, Ruby-like expressions
702
+ let :n, shift(a, -1, axis_offset: 1)
703
+ let :s, shift(a, 1, axis_offset: 1)
704
+ let :w, shift(a, -1)
705
+ let :e, shift(a, 1)
706
+ let :nw, shift(n, -1)
707
+ let :ne, shift(n, 1)
708
+ let :sw, shift(s, -1)
709
+ let :se, shift(s, 1)
486
710
 
487
- ### Use Sugar-Free Syntax When:
488
- - ✅ Generating schemas programmatically
489
- - ✅ Building dynamic schemas in loops/methods
490
- - ✅ You need explicit control over function calls
491
- - ✅ Working with complex nested expressions
492
- - ✅ Debugging expression evaluation issues
711
+ let :neighbors, fn(:sum, [n, s, w, e, nw, ne, sw, se])
493
712
 
494
- ## Syntax Limitations
713
+ let :alive, a > 0
714
+ let :n3_alive, neighbors == 3
715
+ let :n2_alive, neighbors == 2
716
+ let :keep_alive, n2_alive & alive
717
+ let :next_alive, n3_alive | keep_alive
718
+
719
+ value :next_state, select(next_alive, 1, 0)
720
+ end
721
+ ```
722
+
723
+ ### Hierarchical Organization Analysis
724
+
725
+ ```kumi
726
+ schema do
727
+ input do
728
+ array :departments do
729
+ hash :dept do
730
+ string :dept_name
731
+ array :teams do
732
+ hash :team do
733
+ string :team_name
734
+ integer :headcount
735
+ end
736
+ end
737
+ end
738
+ end
739
+ end
740
+
741
+ value :dept_headcount, fn(:sum, input.departments.dept.teams.team.headcount)
742
+ value :teams_per_dept, fn(:count, input.departments.dept.teams.team.team_name)
743
+ value :avg_headcount_per_dept, dept_headcount / teams_per_dept
744
+
745
+ trait :is_above_average_team,
746
+ input.departments.dept.teams.team.headcount > avg_headcount_per_dept
747
+ end
748
+ ```
495
749
 
496
- ### Sugar Syntax Limitations:
497
- - Supports `&` for logical AND (no `&&` due to Ruby precedence)
498
- - Supports `|` for logical OR
499
- - Limited operator precedence control
500
- - Some Ruby methods not available as sugar
501
- - **Refinement scope**: Array methods like `.max` on syntax expressions may not work in certain contexts (e.g., test helpers, Ruby < 3.0). Use `fn(:max, array)` instead.
750
+ ---
502
751
 
503
- ### Sugar-Free Advantages:
504
- - Full access to all registered functions
505
- - Clear operator precedence through explicit nesting
506
- - Works in all contexts (including programmatic generation)
507
- - More explicit about what operations are being performed
752
+ ## Best Practices
508
753
 
509
- ## Performance Notes
754
+ **Do:**
755
+ - Use `trait` for boolean conditions
756
+ - Use `fn(:array_size, ...)` instead of hardcoding lengths
757
+ - Name intermediate values with `let` for clarity
758
+ - Think about which dimension you're reducing
759
+ - Remember axes align by lineage, not name
510
760
 
511
- Both syntaxes compile to identical internal representations, so there is **no performance difference** between sugar and sugar-free syntax. Choose based on readability and maintenance needs.
761
+ **Don't:**
762
+ - Forget that aggregation functions reduce dimensionality
763
+ - Hardcode array sizes
764
+ - Mix up `axis_offset` values (0 = inner/x, 1 = outer/y)