kumi 0.0.29 → 0.0.30

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -1
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +5 -6
  5. data/docs/DEVELOPMENT.md +23 -1
  6. data/docs/GOLDEN_QUICK_START.md +141 -0
  7. data/docs/GOLDEN_TESTS.md +240 -0
  8. data/golden/array_element/expected/schema_ruby.rb +1 -1
  9. data/golden/array_index/expected/schema_ruby.rb +1 -1
  10. data/golden/array_operations/expected/schema_ruby.rb +1 -1
  11. data/golden/cascade_logic/expected/schema_ruby.rb +1 -1
  12. data/golden/chained_fusion/expected/schema_ruby.rb +1 -1
  13. data/golden/decimal_explicit/expected/schema_ruby.rb +1 -1
  14. data/golden/element_arrays/expected/schema_ruby.rb +1 -1
  15. data/golden/empty_and_null_inputs/expected/schema_ruby.rb +1 -1
  16. data/golden/function_overload/expected/schema_ruby.rb +1 -1
  17. data/golden/game_of_life/expected/schema_ruby.rb +1 -1
  18. data/golden/hash_keys/expected/schema_ruby.rb +1 -1
  19. data/golden/hash_value/expected/schema_ruby.rb +1 -1
  20. data/golden/hierarchical_complex/expected/schema_ruby.rb +1 -1
  21. data/golden/inline_rename_scope_leak/expected/schema_ruby.rb +1 -1
  22. data/golden/input_reference/expected/schema_ruby.rb +1 -1
  23. data/golden/interleaved_fusion/expected/schema_ruby.rb +1 -1
  24. data/golden/let_inline/expected/schema_ruby.rb +1 -1
  25. data/golden/loop_fusion/expected/schema_ruby.rb +1 -1
  26. data/golden/min_reduce_scope/expected/schema_ruby.rb +1 -1
  27. data/golden/mixed_dimensions/expected/schema_ruby.rb +1 -1
  28. data/golden/multirank_hoisting/expected/schema_ruby.rb +1 -1
  29. data/golden/nested_hash/expected/schema_ruby.rb +1 -1
  30. data/golden/reduction_broadcast/expected/schema_ruby.rb +1 -1
  31. data/golden/roll/expected/schema_ruby.rb +1 -1
  32. data/golden/shift/expected/schema_ruby.rb +1 -1
  33. data/golden/shift_2d/expected/schema_ruby.rb +1 -1
  34. data/golden/simple_math/expected/schema_ruby.rb +1 -1
  35. data/golden/streaming_basics/expected/schema_ruby.rb +1 -1
  36. data/golden/tuples/expected/schema_ruby.rb +1 -1
  37. data/golden/tuples_and_arrays/expected/schema_ruby.rb +1 -1
  38. data/golden/us_tax_2024/expected/schema_ruby.rb +1 -1
  39. data/golden/with_constants/expected/schema_ruby.rb +1 -1
  40. data/lib/kumi/analyzer.rb +39 -79
  41. data/lib/kumi/core/analyzer/analysis_state.rb +2 -0
  42. data/lib/kumi/core/analyzer/constant_evaluator.rb +0 -2
  43. data/lib/kumi/core/analyzer/execution_phase.rb +24 -0
  44. data/lib/kumi/core/analyzer/execution_result.rb +38 -0
  45. data/lib/kumi/core/analyzer/pass_failure.rb +26 -0
  46. data/lib/kumi/core/analyzer/pass_manager.rb +136 -0
  47. data/lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb +1 -1
  48. data/lib/kumi/core/analyzer/passes/codegen/js_pass.rb +1 -1
  49. data/lib/kumi/core/analyzer/passes/codegen/ruby/declaration_emitter.rb +1 -1
  50. data/lib/kumi/core/analyzer/passes/codegen/ruby_pass.rb +1 -1
  51. data/lib/kumi/core/analyzer/passes/constant_folding_pass.rb +1 -1
  52. data/lib/kumi/core/analyzer/passes/formal_constraint_propagator.rb +13 -31
  53. data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +1 -1
  54. data/lib/kumi/core/analyzer/passes/input_collector.rb +1 -1
  55. data/lib/kumi/core/analyzer/passes/input_form_schema_pass.rb +1 -1
  56. data/lib/kumi/core/analyzer/passes/lir/loop_invariant_code_motion_pass.rb +1 -1
  57. data/lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb +0 -2
  58. data/lib/kumi/core/analyzer/passes/normalize_to_nast_pass.rb +5 -1
  59. data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +2 -1
  60. data/lib/kumi/core/analyzer/passes/snast_pass.rb +1 -1
  61. data/lib/kumi/core/analyzer/passes/unsat_detector.rb +8 -10
  62. data/lib/kumi/core/compiler/access_planner_v2.rb +1 -2
  63. data/lib/kumi/core/functions/overload_resolver.rb +15 -19
  64. data/lib/kumi/core/functions/type_categories.rb +3 -3
  65. data/lib/kumi/core/functions/type_error_reporter.rb +1 -3
  66. data/lib/kumi/core/input/type_matcher.rb +1 -1
  67. data/lib/kumi/core/types/normalizer.rb +8 -10
  68. data/lib/kumi/core/types/validator.rb +1 -1
  69. data/lib/kumi/core/types/value_objects.rb +5 -2
  70. data/lib/kumi/core/types.rb +2 -4
  71. data/lib/kumi/dev/codegen.rb +1 -1
  72. data/lib/kumi/dev/golden/generator.rb +14 -10
  73. data/lib/kumi/dev/golden/reporter.rb +5 -5
  74. data/lib/kumi/dev/golden/representation.rb +1 -3
  75. data/lib/kumi/dev/golden/result.rb +1 -1
  76. data/lib/kumi/dev/golden/runtime_test.rb +0 -2
  77. data/lib/kumi/dev/golden/suite.rb +20 -4
  78. data/lib/kumi/dev/golden/value_normalizer.rb +1 -3
  79. data/lib/kumi/doc_generator/formatters/json.rb +11 -11
  80. data/lib/kumi/doc_generator/formatters/markdown.rb +35 -37
  81. data/lib/kumi/doc_generator/loader.rb +8 -6
  82. data/lib/kumi/doc_generator/merger.rb +12 -12
  83. data/lib/kumi/frontends/text.rb +4 -6
  84. data/lib/kumi/registry_v2/loader.rb +32 -33
  85. data/lib/kumi/schema.rb +2 -2
  86. data/lib/kumi/version.rb +1 -1
  87. metadata +13 -14
  88. data/debug_ordering.rb +0 -52
  89. data/examples/deep_schema_compilation_and_evaluation_benchmark.rb +0 -106
  90. data/examples/federal_tax_calculator_2024.rb +0 -115
  91. data/examples/game_of_life.rb +0 -95
  92. data/examples/simple_rpg_game.rb +0 -1000
  93. data/examples/static_analysis_errors.rb +0 -178
  94. data/examples/wide_schema_compilation_and_evaluation_benchmark.rb +0 -80
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # U.S. federal income‑tax plus FICA
4
-
5
- require_relative "../lib/kumi"
6
-
7
- module Tax2024
8
- FED_BREAKS_SINGLE = [11_600, 47_150, 100_525, 191_950,
9
- 243_725, 609_350, Float::INFINITY].freeze
10
-
11
- FED_BREAKS_MARRIED = [23_200, 94_300, 201_050, 383_900,
12
- 487_450, 731_200, Float::INFINITY].freeze
13
-
14
- FED_BREAKS_SEPARATE = [11_600, 47_150, 100_525, 191_950,
15
- 243_725, 365_600, Float::INFINITY].freeze
16
-
17
- FED_BREAKS_HOH = [16_550, 63_100, 100_500, 191_950,
18
- 243_700, 609_350, Float::INFINITY].freeze
19
-
20
- FED_RATES = [0.10, 0.12, 0.22, 0.24,
21
- 0.32, 0.35, 0.37].freeze
22
- end
23
-
24
- module FederalTaxCalculator
25
- extend Kumi::Schema
26
- include Tax2024
27
-
28
- schema do
29
- input do
30
- float :income
31
- string :filing_status, domain: %w[single married_joint married_separate head_of_household]
32
- end
33
-
34
- # ── standard deduction table ───────────────────────────────────────
35
- trait :single, input.filing_status == "single"
36
- trait :married, input.filing_status == "married_joint"
37
- trait :separate, input.filing_status == "married_separate"
38
- trait :hoh, input.filing_status == "head_of_household"
39
-
40
- value :std_deduction do
41
- on single, 14_600
42
- on married, 29_200
43
- on separate, 14_600
44
- base 21_900 # HOH default
45
- end
46
-
47
- value :taxable_income, [input.income - std_deduction, 0].max
48
-
49
- value :fed_breaks do
50
- on single, FED_BREAKS_SINGLE
51
- on married, FED_BREAKS_MARRIED
52
- on separate, FED_BREAKS_SEPARATE
53
- on hoh, FED_BREAKS_HOH
54
- end
55
-
56
- value :fed_rates, FED_RATES
57
- value :fed_calc,
58
- fn(:piecewise_sum, taxable_income, fed_breaks, fed_rates)
59
-
60
- value :fed_tax, fed_calc[0]
61
- value :fed_marginal, fed_calc[1]
62
- value :fed_eff, fed_tax / [input.income, 1.0].max
63
-
64
- # ── FICA (employee share) ─────────────────────────────────────────────
65
- value :ss_wage_base, 168_600.0
66
- value :ss_rate, 0.062
67
-
68
- value :med_base_rate, 0.0145
69
- value :addl_med_rate, 0.009
70
-
71
- # additional‑Medicare threshold depends on filing status
72
- value :addl_threshold do
73
- on single, 200_000
74
- on married, 250_000
75
- on separate, 125_000
76
- base 200_000 # HOH same as single
77
- end
78
-
79
- # social‑security portion (capped)
80
- value :ss_tax, [input.income, ss_wage_base].min * ss_rate
81
-
82
- # medicare (1.45 % on everything)
83
- value :med_tax, input.income * med_base_rate
84
-
85
- # additional medicare on income above threshold
86
- value :addl_med_tax, [input.income - addl_threshold, 0].max * addl_med_rate
87
-
88
- value :fica_tax, ss_tax + med_tax + addl_med_tax
89
- value :fica_eff, fica_tax / [input.income, 1.0].max
90
-
91
- # ── Totals ─────────────────────────────────────────────────────────
92
- value :total_tax, fed_tax + fica_tax
93
-
94
- value :total_eff, total_tax / fn(:max, [input.income, 1.0])
95
- value :after_tax, input.income - total_tax
96
- end
97
- end
98
-
99
- def print_tax_summary(args)
100
- r = FederalTaxCalculator.from(args)
101
- puts "\n=== 2024 U.S. Income‑Tax Example ==="
102
- printf "Income: $%0.2f\n", args[:income]
103
- puts "Filing status: #{args[:filing_status]}\n\n"
104
-
105
- puts "Federal tax: $#{r[:fed_tax].round(2)} (#{(r[:fed_eff] * 100).round(2)}% effective)"
106
- puts "FICA tax: $#{r[:fica_tax].round(2)} (#{(r[:fica_eff] * 100).round(2)}% effective)"
107
- puts "Total tax: $#{r[:total_tax].round(2)} (#{(r[:total_eff] * 100).round(2)}% effective)"
108
- puts "After-tax income: $#{r[:after_tax].round(2)}"
109
- end
110
-
111
-
112
- input = { income: 1_000_000,
113
- filing_status: "single"
114
- }
115
- print_tax_summary(input)
@@ -1,95 +0,0 @@
1
- require "kumi"
2
-
3
- begin
4
- # in a block so we dont define this globally
5
- def neighbor_cells_sum_method(cells, row, col, height, width)
6
- # Calculate neighbor indices with wraparound
7
- [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]].map do |dr, dc|
8
- neighbor_row = (row + dr) % height
9
- neighbor_col = (col + dc) % width
10
- neighbor_index = (neighbor_row * width) + neighbor_col
11
- cells[neighbor_index]
12
- end.sum
13
- end
14
- Kumi::Registry.register_with_metadata(:neighbor_cells_sum, method(:neighbor_cells_sum_method),
15
- return_type: :integer, arity: 5,
16
- param_types: %i[array integer integer integer integer],
17
- description: "Get neighbor cells for Conway's Game of Life")
18
- end
19
-
20
- module GameOfLife
21
- extend Kumi::Schema
22
- WIDTH = 50
23
- HEIGHT = 30
24
-
25
- schema do
26
- # Complete Game of Life engine - computes entire next generation
27
- input do
28
- array :cells, elem: { type: :integer }
29
- end
30
-
31
- # Generate next state for every cell in the grid
32
- next_cell_values = []
33
-
34
- (0...HEIGHT).each do |row|
35
- (0...WIDTH).each do |col|
36
- # Neighbor count and current state for this cell
37
- cell_index = (row * WIDTH) + col
38
- value :"neighbor_sum_#{cell_index}", fn(:neighbor_cells_sum, input.cells, row, col, HEIGHT, WIDTH)
39
-
40
- # Game of Life rules: (alive && neighbors == 2) || (neighbors == 3)
41
- trait :"cell_#{cell_index}_alive",
42
- ((input.cells[cell_index] == 1) & (ref(:"neighbor_sum_#{cell_index}") == 2)) |
43
- (ref(:"neighbor_sum_#{cell_index}") == 3)
44
-
45
- # Next state for this cell
46
- value :"cell_#{cell_index}_next" do
47
- on :"cell_#{cell_index}_alive", 1
48
- base 0
49
- end
50
-
51
- next_cell_values << ref(:"cell_#{cell_index}_next")
52
- end
53
- end
54
-
55
- # Complete next generation as array
56
- value :next_cells, next_cell_values
57
-
58
- # Render current state as visual string
59
- value :cell_symbols, fn(:map_conditional, input.cells, 1, "█", " ")
60
- value :grid_rows, fn(:each_slice, cell_symbols, WIDTH)
61
- value :rendered_grid, fn(:map_join_rows, grid_rows, "", "\n")
62
- end
63
- end
64
-
65
- # # Helper to pretty‑print the grid
66
- def render(cells, width)
67
- cells.each_slice(width) do |row|
68
- puts row.map { |v| v == 1 ? "█" : " " }.join
69
- end
70
- end
71
-
72
- # # Bootstrap a simple glider on a 10×10 grid
73
- width = GameOfLife::WIDTH
74
- height = GameOfLife::HEIGHT
75
- cells = Array.new(width * height, 0)
76
- # Glider pattern
77
- [[1, 1], [2, 3], [3, 1], [3, 2], [3, 3]].each { |r, c| cells[(r * width) + c] = 1 }
78
-
79
- 10_000.times do |gen|
80
- system("clear") || system("cls")
81
- puts "Conway's Game of Life - Generation #{gen}"
82
- puts ""
83
-
84
- # Create schema instance for this generation
85
- runner = GameOfLife.from(cells: cells)
86
-
87
- # Render using Kumi instead of Ruby function!
88
- rendered_output = runner[:rendered_grid]
89
- puts rendered_output
90
-
91
- # Calculate next generation with single schema call!
92
- cells = runner[:next_cells]
93
-
94
- sleep 0.1
95
- end