kumi 0.0.21 → 0.0.23
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/CHANGELOG.md +10 -0
- data/README.md +59 -115
- data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +6 -4
- data/lib/kumi/core/functions/function_spec.rb +16 -0
- data/lib/kumi/core/functions/loader.rb +2 -2
- data/lib/kumi/version.rb +1 -1
- metadata +2 -11
- data/lib/kumi/compiler.rb +0 -21
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +0 -816
- data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +0 -907
- data/lib/kumi/core/analyzer/passes/scope_resolution_pass.rb +0 -349
- data/lib/kumi/core/analyzer/passes/type_checker.rb +0 -179
- data/lib/kumi/core/analyzer/passes/type_inferencer_pass.rb +0 -234
- data/lib/kumi/core/compiler_base.rb +0 -137
- data/lib/kumi/core/explain.rb +0 -254
- data/lib/kumi/core/functions/model.rb +0 -10
- data/lib/kumi/schema_metadata.rb +0 -524
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb114ffa6a4c06a4a5c517757ba3030043095e62b54e15b206989cdcd10329fd
|
4
|
+
data.tar.gz: db8aa5df3fec33213cb27478523b24d3f94812b55e59ba5c39105f5ec1ae9a21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4af4d0d9406226983cf67d4cdf22b366fb01588c977cca449bbd221c5c25a633f04f98f0b9982c44228c526b452306a4c374cac823972581d9e0f4d7c368870
|
7
|
+
data.tar.gz: 73cf1f508cf9501177b80014bbf28c111979057191bc4643a2749339dabe85dcdee46e202825ec285a378b301540d23aa67d7d4ff39e343a7c5f833c62b6d199
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
|
+
|
3
|
+
## [0.0.23] – 2025-10-13
|
4
|
+
### Fixed
|
5
|
+
- OutputSchemaPass now excludes inline `:let` declarations from output_schema metadata, matching JS/Ruby codegen behavior
|
6
|
+
|
7
|
+
## [0.0.22] – 2025-10-13
|
8
|
+
### Removed
|
9
|
+
- Legacy analyzer passes and compiler components referencing old Registry and Runtime APIs
|
10
|
+
- Obsolete test files that depended on removed infrastructure
|
11
|
+
|
2
12
|
## [0.0.21] – 2025-10-13
|
3
13
|
Fix - update Gemfile.lock to current version
|
4
14
|
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[](https://github.com/amuta/kumi/actions)
|
4
4
|
[](https://badge.fury.io/rb/kumi)
|
5
5
|
|
6
|
+
**[Try the interactive demo →](https://kumi-play.example.com)**
|
6
7
|
|
7
8
|
---
|
8
9
|
|
@@ -13,23 +14,15 @@
|
|
13
14
|
---
|
14
15
|
|
15
16
|
|
16
|
-
|
17
|
+
**Declarative calculation DSL for Ruby.** Write business rules once, run them anywhere.
|
17
18
|
|
18
|
-
-
|
19
|
-
- Performs **static validation** at definition time.
|
20
|
-
- Lowers to a **portable Low-level IR (LIR)**.
|
21
|
-
- Code-generates standalone **Ruby** and **JavaScript**.
|
19
|
+
Kumi compiles high-level schemas into standalone Ruby and JavaScript with no runtime dependencies.
|
22
20
|
|
23
|
-
|
21
|
+
**Built for:** finance, tax, pricing, insurance, payroll, analytics—domains where correctness and transparency matter.
|
24
22
|
|
25
23
|
---
|
26
24
|
|
27
|
-
##
|
28
|
-
|
29
|
-
*Note: this is not available on the last published gem version (0.0.18), but if you clone this repository you can just copy a ./golden/$schema_name and modify schema.kumi as you and run bin/kumi golden test $schema_name*
|
30
|
-
|
31
|
-
|
32
|
-
Kumi emits the kernel for your schema with no runtime in the target language. You can use it within your ruby application backend and/or export to the client.
|
25
|
+
## Example: Conway's Game of Life
|
33
26
|
|
34
27
|
|
35
28
|
<details>
|
@@ -78,114 +71,39 @@ end
|
|
78
71
|
|
79
72
|
</details>
|
80
73
|
|
81
|
-
<details>
|
82
|
-
<summary><strong>Optimized LIR (lowered IR)</strong></summary>
|
83
|
-
|
84
|
-
```bash
|
85
|
-
# ...
|
86
|
-
(Declaration next_state
|
87
|
-
%t285 = load_input "rows" :: array
|
88
|
-
%t1539 = Length %t285 :: integer
|
89
|
-
%t1540 = const -1 :: integer
|
90
|
-
%t1542 = const 0 :: integer
|
91
|
-
%t1546 = const 1 :: integer
|
92
|
-
%t1334 = const 3 :: integer
|
93
|
-
%t1339 = const 2 :: integer
|
94
|
-
%t1547 = call core.sub(%t1539, %t1546) :: integer
|
95
|
-
loop rows id=L31 in %t285 as el=%rows_el_286, idx=%rows_i_287
|
96
|
-
%t1541 = call core.sub(%rows_i_287, %t1540) :: integer
|
97
|
-
%t1561 = call core.sub(%rows_i_287, %t1546) :: integer
|
98
|
-
%t1580 = call core.mod(%rows_i_287, %t1539) :: integer
|
99
|
-
# ...
|
100
|
-
```
|
101
|
-
|
102
|
-
</details>
|
103
|
-
|
104
|
-
<details>
|
105
|
-
<summary><strong>Generated Ruby (excerpt)</strong></summary>
|
106
|
-
|
107
|
-
```ruby
|
108
|
-
# Autogenerated by Kumi Codegen
|
109
|
-
module Kumi::Compiled::KUMI_bd17a3ebee1bec4e58b72118d43e8c1c93bf773f257fc93d9c32a783d212ea4f
|
110
|
-
def self.from(input_data = nil)
|
111
|
-
instance = Object.new
|
112
|
-
instance.extend(self)
|
113
|
-
instance.instance_variable_set(:@input, input_data)
|
114
|
-
instance
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.__kumi_executable__
|
118
|
-
instance = Object.new
|
119
|
-
instance.extend(self)
|
120
|
-
instance
|
121
|
-
end
|
122
|
-
|
123
|
-
def update(input_data)
|
124
|
-
@input = @input.merge(input_data)
|
125
|
-
self
|
126
|
-
end
|
127
|
-
|
128
|
-
def [](name)
|
129
|
-
case name
|
130
|
-
when :next_state then _next_state
|
131
|
-
else raise KeyError, "Unknown declaration"
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def _next_state(input = @input)
|
136
|
-
out = []
|
137
|
-
t285 = input["rows"] || input[:rows]
|
138
|
-
t1539 = t285.length
|
139
|
-
t1540 = -1
|
140
|
-
t1542 = 0
|
141
|
-
t1546 = 1
|
142
|
-
t1334 = 3
|
143
|
-
t1339 = 2
|
144
|
-
t1547 = t1539 - t1546
|
145
|
-
t285.each_with_index do |rows_el_286, rows_i_287|
|
146
|
-
out_1 = []
|
147
|
-
t1541 = rows_i_287 - t1540
|
148
|
-
t1561 = rows_i_287 - t1546
|
149
|
-
t1580 = rows_i_287 % t1539
|
150
|
-
t1543 = t1541 >= t1542
|
151
|
-
t1544 = t1541 < t1539
|
152
|
-
t1549 = [[ t1541, t1542 ].max, t1547 ].min
|
153
|
-
t1563 = t1561 >= t1542
|
154
|
-
# ...
|
155
|
-
```
|
156
|
-
|
157
|
-
</details>
|
158
74
|
|
159
75
|
<details>
|
160
76
|
<summary><strong>Generated JavaScript (excerpt)</strong></summary>
|
161
77
|
|
162
78
|
```js
|
163
|
-
export
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
79
|
+
export function _next_state(input) {
|
80
|
+
let out = [];
|
81
|
+
let t285 = input["rows"];
|
82
|
+
let t1539 = t285.length;
|
83
|
+
const t1540 = -1;
|
84
|
+
const t1542 = 0;
|
85
|
+
const t1546 = 1;
|
86
|
+
const t1334 = 3;
|
87
|
+
const t1339 = 2;
|
88
|
+
let t1547 = t1539 - t1546;
|
89
|
+
t285.forEach((rows_el_286, rows_i_287) => {
|
90
|
+
let out_1 = [];
|
91
|
+
let t1541 = rows_i_287 - t1540;
|
92
|
+
let t1561 = rows_i_287 - t1546;
|
93
|
+
let t1580 = ((rows_i_287 % t1539) + t1539) % t1539;
|
94
|
+
// ... neighbor calculations, Conway's rules
|
95
|
+
let t1332 = [t1557, t1577, t1597, t1617, t1645, t1673, t1701, t1729];
|
96
|
+
let t1333 = t1332.reduce((a, b) => a + b, 0);
|
97
|
+
let t1335 = t1333 == t1334;
|
98
|
+
let t1340 = t1333 == t1339;
|
99
|
+
let t1344 = col_el_288 > t1542;
|
100
|
+
let t1345 = t1340 && t1344;
|
101
|
+
let t528 = t1335 || t1345;
|
102
|
+
let t293 = t528 ? t1546 : t1542;
|
103
|
+
out_1.push(t293);
|
104
|
+
});
|
105
|
+
return out;
|
106
|
+
}
|
189
107
|
```
|
190
108
|
|
191
109
|
</details>
|
@@ -200,6 +118,32 @@ gem install kumi
|
|
200
118
|
|
201
119
|
Requires Ruby 3.1+. No external dependencies.
|
202
120
|
|
121
|
+
## Quick Start
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
require 'kumi'
|
125
|
+
|
126
|
+
Kumi.configure do |config|
|
127
|
+
config.compilation_mode = :jit
|
128
|
+
end
|
129
|
+
|
130
|
+
module Double
|
131
|
+
extend Kumi::Schema
|
132
|
+
|
133
|
+
schema do
|
134
|
+
input { integer :x }
|
135
|
+
value :doubled, input.x * 2
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Execute in Ruby
|
140
|
+
result = Double.from(x: 5)
|
141
|
+
result[:doubled] # => 10
|
142
|
+
|
143
|
+
# Export to JavaScript
|
144
|
+
Double.write_source("output.mjs", platform: :javascript)
|
145
|
+
```
|
146
|
+
|
203
147
|
---
|
204
148
|
|
205
149
|
## License
|
@@ -9,15 +9,17 @@ module Kumi
|
|
9
9
|
snast_module = get_state(:snast_module)
|
10
10
|
return state unless snast_module
|
11
11
|
|
12
|
-
|
12
|
+
hints = get_state(:hints)
|
13
|
+
output_schema = build_output_schema(snast_module, hints)
|
13
14
|
state.with(:output_schema, output_schema.freeze)
|
14
15
|
end
|
15
16
|
|
16
17
|
private
|
17
18
|
|
18
|
-
def build_output_schema(snast_module)
|
19
|
-
snast_module.decls.
|
20
|
-
|
19
|
+
def build_output_schema(snast_module, hints)
|
20
|
+
snast_module.decls.each_with_object({}) do |(name, decl), acc|
|
21
|
+
next if hints[name][:inline]
|
22
|
+
acc[name] = build_output_field(decl)
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kumi
|
4
|
+
module Core
|
5
|
+
module Functions
|
6
|
+
# Minimal function specification for NAST dimensional analysis
|
7
|
+
FunctionSpec = Struct.new(
|
8
|
+
:id, # "core.add"
|
9
|
+
:kind, # :elementwise, :reduce, :constructor
|
10
|
+
:parameter_names, # [:left_operand, :right_operand]
|
11
|
+
:dtype_rule, # "promote(left_operand,right_operand)" or proc
|
12
|
+
keyword_init: true
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "yaml"
|
4
|
-
require_relative "
|
4
|
+
require_relative "function_spec"
|
5
5
|
require_relative "type_rules"
|
6
6
|
|
7
7
|
module Kumi
|
@@ -34,7 +34,7 @@ module Kumi
|
|
34
34
|
parameter_names = (fn_hash["params"] || []).map { |p| p["name"].to_sym }
|
35
35
|
dtype_rule_fn = TypeRules.compile_dtype_rule(fn_hash.fetch("dtype"), parameter_names)
|
36
36
|
|
37
|
-
FunctionSpec.new(
|
37
|
+
Functions::FunctionSpec.new(
|
38
38
|
id: function_id,
|
39
39
|
kind: function_kind,
|
40
40
|
parameter_names: parameter_names,
|
data/lib/kumi/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- André Muta
|
@@ -537,7 +537,6 @@ files:
|
|
537
537
|
- golden/with_constants/schema.kumi
|
538
538
|
- lib/kumi.rb
|
539
539
|
- lib/kumi/analyzer.rb
|
540
|
-
- lib/kumi/compiler.rb
|
541
540
|
- lib/kumi/configuration.rb
|
542
541
|
- lib/kumi/core/analyzer/analysis_state.rb
|
543
542
|
- lib/kumi/core/analyzer/binder.rb
|
@@ -551,7 +550,6 @@ files:
|
|
551
550
|
- lib/kumi/core/analyzer/passes/assemble_irv2_pass.rb
|
552
551
|
- lib/kumi/core/analyzer/passes/attach_anchors_pass.rb
|
553
552
|
- lib/kumi/core/analyzer/passes/attach_terminal_info_pass.rb
|
554
|
-
- lib/kumi/core/analyzer/passes/broadcast_detector.rb
|
555
553
|
- lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb
|
556
554
|
- lib/kumi/core/analyzer/passes/codegen/js/emitter.rb
|
557
555
|
- lib/kumi/core/analyzer/passes/codegen/js/output_buffer.rb
|
@@ -583,7 +581,6 @@ files:
|
|
583
581
|
- lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb
|
584
582
|
- lib/kumi/core/analyzer/passes/lir/validation_pass.rb
|
585
583
|
- lib/kumi/core/analyzer/passes/load_input_cse.rb
|
586
|
-
- lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb
|
587
584
|
- lib/kumi/core/analyzer/passes/lower_to_irv2_pass.rb
|
588
585
|
- lib/kumi/core/analyzer/passes/name_indexer.rb
|
589
586
|
- lib/kumi/core/analyzer/passes/nast_dimensional_analyzer_pass.rb
|
@@ -591,12 +588,9 @@ files:
|
|
591
588
|
- lib/kumi/core/analyzer/passes/output_schema_pass.rb
|
592
589
|
- lib/kumi/core/analyzer/passes/pass_base.rb
|
593
590
|
- lib/kumi/core/analyzer/passes/precompute_access_paths_pass.rb
|
594
|
-
- lib/kumi/core/analyzer/passes/scope_resolution_pass.rb
|
595
591
|
- lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb
|
596
592
|
- lib/kumi/core/analyzer/passes/snast_pass.rb
|
597
593
|
- lib/kumi/core/analyzer/passes/toposorter.rb
|
598
|
-
- lib/kumi/core/analyzer/passes/type_checker.rb
|
599
|
-
- lib/kumi/core/analyzer/passes/type_inferencer_pass.rb
|
600
594
|
- lib/kumi/core/analyzer/passes/unsat_detector.rb
|
601
595
|
- lib/kumi/core/analyzer/passes/visitor_pass.rb
|
602
596
|
- lib/kumi/core/analyzer/plans.rb
|
@@ -619,7 +613,6 @@ files:
|
|
619
613
|
- lib/kumi/core/compiler/accessors/materialize_accessor.rb
|
620
614
|
- lib/kumi/core/compiler/accessors/ravel_accessor.rb
|
621
615
|
- lib/kumi/core/compiler/accessors/read_accessor.rb
|
622
|
-
- lib/kumi/core/compiler_base.rb
|
623
616
|
- lib/kumi/core/constraint_relationship_solver.rb
|
624
617
|
- lib/kumi/core/domain/enum_analyzer.rb
|
625
618
|
- lib/kumi/core/domain/range_analyzer.rb
|
@@ -628,7 +621,6 @@ files:
|
|
628
621
|
- lib/kumi/core/error_reporter.rb
|
629
622
|
- lib/kumi/core/error_reporting.rb
|
630
623
|
- lib/kumi/core/errors.rb
|
631
|
-
- lib/kumi/core/explain.rb
|
632
624
|
- lib/kumi/core/export.rb
|
633
625
|
- lib/kumi/core/export/deserializer.rb
|
634
626
|
- lib/kumi/core/export/errors.rb
|
@@ -636,8 +628,8 @@ files:
|
|
636
628
|
- lib/kumi/core/export/node_registry.rb
|
637
629
|
- lib/kumi/core/export/node_serializers.rb
|
638
630
|
- lib/kumi/core/export/serializer.rb
|
631
|
+
- lib/kumi/core/functions/function_spec.rb
|
639
632
|
- lib/kumi/core/functions/loader.rb
|
640
|
-
- lib/kumi/core/functions/model.rb
|
641
633
|
- lib/kumi/core/functions/type_rules.rb
|
642
634
|
- lib/kumi/core/input/type_matcher.rb
|
643
635
|
- lib/kumi/core/input/validator.rb
|
@@ -716,7 +708,6 @@ files:
|
|
716
708
|
- lib/kumi/registry_v2.rb
|
717
709
|
- lib/kumi/registry_v2/loader.rb
|
718
710
|
- lib/kumi/schema.rb
|
719
|
-
- lib/kumi/schema_metadata.rb
|
720
711
|
- lib/kumi/support/diff.rb
|
721
712
|
- lib/kumi/support/ir_render.rb
|
722
713
|
- lib/kumi/support/lir_printer.rb
|
data/lib/kumi/compiler.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
# Compiles an analyzed schema into executable lambdas
|
5
|
-
class Compiler < Core::CompilerBase
|
6
|
-
def self.compile(schema, analyzer:, schema_name: nil)
|
7
|
-
new(schema, analyzer, schema_name: schema_name).compile
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(schema, analyzer, schema_name: nil)
|
11
|
-
super(schema, analyzer)
|
12
|
-
@bindings = {}
|
13
|
-
@schema_name = schema_name
|
14
|
-
end
|
15
|
-
|
16
|
-
def compile
|
17
|
-
# Switch to LIR: Use the analysis state instead of old compilation
|
18
|
-
Runtime::Executable.from_analysis(@analysis.state, schema_name: @schema_name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|