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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/CHANGELOG.md +12 -0
- data/README.md +5 -6
- data/docs/DEVELOPMENT.md +23 -1
- data/docs/GOLDEN_QUICK_START.md +141 -0
- data/docs/GOLDEN_TESTS.md +240 -0
- data/golden/array_element/expected/schema_ruby.rb +1 -1
- data/golden/array_index/expected/schema_ruby.rb +1 -1
- data/golden/array_operations/expected/schema_ruby.rb +1 -1
- data/golden/cascade_logic/expected/schema_ruby.rb +1 -1
- data/golden/chained_fusion/expected/schema_ruby.rb +1 -1
- data/golden/decimal_explicit/expected/schema_ruby.rb +1 -1
- data/golden/element_arrays/expected/schema_ruby.rb +1 -1
- data/golden/empty_and_null_inputs/expected/schema_ruby.rb +1 -1
- data/golden/function_overload/expected/schema_ruby.rb +1 -1
- data/golden/game_of_life/expected/schema_ruby.rb +1 -1
- data/golden/hash_keys/expected/schema_ruby.rb +1 -1
- data/golden/hash_value/expected/schema_ruby.rb +1 -1
- data/golden/hierarchical_complex/expected/schema_ruby.rb +1 -1
- data/golden/inline_rename_scope_leak/expected/schema_ruby.rb +1 -1
- data/golden/input_reference/expected/schema_ruby.rb +1 -1
- data/golden/interleaved_fusion/expected/schema_ruby.rb +1 -1
- data/golden/let_inline/expected/schema_ruby.rb +1 -1
- data/golden/loop_fusion/expected/schema_ruby.rb +1 -1
- data/golden/min_reduce_scope/expected/schema_ruby.rb +1 -1
- data/golden/mixed_dimensions/expected/schema_ruby.rb +1 -1
- data/golden/multirank_hoisting/expected/schema_ruby.rb +1 -1
- data/golden/nested_hash/expected/schema_ruby.rb +1 -1
- data/golden/reduction_broadcast/expected/schema_ruby.rb +1 -1
- data/golden/roll/expected/schema_ruby.rb +1 -1
- data/golden/shift/expected/schema_ruby.rb +1 -1
- data/golden/shift_2d/expected/schema_ruby.rb +1 -1
- data/golden/simple_math/expected/schema_ruby.rb +1 -1
- data/golden/streaming_basics/expected/schema_ruby.rb +1 -1
- data/golden/tuples/expected/schema_ruby.rb +1 -1
- data/golden/tuples_and_arrays/expected/schema_ruby.rb +1 -1
- data/golden/us_tax_2024/expected/schema_ruby.rb +1 -1
- data/golden/with_constants/expected/schema_ruby.rb +1 -1
- data/lib/kumi/analyzer.rb +39 -79
- data/lib/kumi/core/analyzer/analysis_state.rb +2 -0
- data/lib/kumi/core/analyzer/constant_evaluator.rb +0 -2
- data/lib/kumi/core/analyzer/execution_phase.rb +24 -0
- data/lib/kumi/core/analyzer/execution_result.rb +38 -0
- data/lib/kumi/core/analyzer/pass_failure.rb +26 -0
- data/lib/kumi/core/analyzer/pass_manager.rb +136 -0
- data/lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/js_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/ruby/declaration_emitter.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/ruby_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/constant_folding_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/formal_constraint_propagator.rb +13 -31
- data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/input_collector.rb +1 -1
- data/lib/kumi/core/analyzer/passes/input_form_schema_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/lir/loop_invariant_code_motion_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb +0 -2
- data/lib/kumi/core/analyzer/passes/normalize_to_nast_pass.rb +5 -1
- data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +2 -1
- data/lib/kumi/core/analyzer/passes/snast_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +8 -10
- data/lib/kumi/core/compiler/access_planner_v2.rb +1 -2
- data/lib/kumi/core/functions/overload_resolver.rb +15 -19
- data/lib/kumi/core/functions/type_categories.rb +3 -3
- data/lib/kumi/core/functions/type_error_reporter.rb +1 -3
- data/lib/kumi/core/input/type_matcher.rb +1 -1
- data/lib/kumi/core/types/normalizer.rb +8 -10
- data/lib/kumi/core/types/validator.rb +1 -1
- data/lib/kumi/core/types/value_objects.rb +5 -2
- data/lib/kumi/core/types.rb +2 -4
- data/lib/kumi/dev/codegen.rb +1 -1
- data/lib/kumi/dev/golden/generator.rb +14 -10
- data/lib/kumi/dev/golden/reporter.rb +5 -5
- data/lib/kumi/dev/golden/representation.rb +1 -3
- data/lib/kumi/dev/golden/result.rb +1 -1
- data/lib/kumi/dev/golden/runtime_test.rb +0 -2
- data/lib/kumi/dev/golden/suite.rb +20 -4
- data/lib/kumi/dev/golden/value_normalizer.rb +1 -3
- data/lib/kumi/doc_generator/formatters/json.rb +11 -11
- data/lib/kumi/doc_generator/formatters/markdown.rb +35 -37
- data/lib/kumi/doc_generator/loader.rb +8 -6
- data/lib/kumi/doc_generator/merger.rb +12 -12
- data/lib/kumi/frontends/text.rb +4 -6
- data/lib/kumi/registry_v2/loader.rb +32 -33
- data/lib/kumi/schema.rb +2 -2
- data/lib/kumi/version.rb +1 -1
- metadata +13 -14
- data/debug_ordering.rb +0 -52
- data/examples/deep_schema_compilation_and_evaluation_benchmark.rb +0 -106
- data/examples/federal_tax_calculator_2024.rb +0 -115
- data/examples/game_of_life.rb +0 -95
- data/examples/simple_rpg_game.rb +0 -1000
- data/examples/static_analysis_errors.rb +0 -178
- 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)
|
data/examples/game_of_life.rb
DELETED
|
@@ -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
|