kumi 0.0.13 → 0.0.14
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/.rspec +0 -1
- data/BACKLOG.md +34 -0
- data/CLAUDE.md +4 -6
- data/README.md +0 -18
- data/config/functions.yaml +352 -0
- data/docs/dev/analyzer-debug.md +52 -0
- data/docs/dev/parse-command.md +64 -0
- data/docs/functions/analyzer_integration.md +199 -0
- data/docs/functions/signatures.md +171 -0
- data/examples/hash_objects_demo.rb +138 -0
- data/golden/array_operations/schema.kumi +17 -0
- data/golden/cascade_logic/schema.kumi +16 -0
- data/golden/mixed_nesting/schema.kumi +42 -0
- data/golden/simple_math/schema.kumi +10 -0
- data/lib/kumi/analyzer.rb +72 -21
- data/lib/kumi/core/analyzer/checkpoint.rb +72 -0
- data/lib/kumi/core/analyzer/debug.rb +167 -0
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +1 -3
- data/lib/kumi/core/analyzer/passes/function_signature_pass.rb +199 -0
- data/lib/kumi/core/analyzer/passes/load_input_cse.rb +120 -0
- data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +72 -157
- data/lib/kumi/core/analyzer/passes/toposorter.rb +37 -1
- data/lib/kumi/core/analyzer/state_serde.rb +64 -0
- data/lib/kumi/core/analyzer/structs/access_plan.rb +12 -10
- data/lib/kumi/core/compiler/access_planner.rb +3 -2
- data/lib/kumi/core/function_registry/collection_functions.rb +3 -1
- data/lib/kumi/core/functions/dimension.rb +98 -0
- data/lib/kumi/core/functions/dtypes.rb +20 -0
- data/lib/kumi/core/functions/errors.rb +11 -0
- data/lib/kumi/core/functions/kernel_adapter.rb +45 -0
- data/lib/kumi/core/functions/loader.rb +119 -0
- data/lib/kumi/core/functions/registry_v2.rb +68 -0
- data/lib/kumi/core/functions/shape.rb +70 -0
- data/lib/kumi/core/functions/signature.rb +122 -0
- data/lib/kumi/core/functions/signature_parser.rb +86 -0
- data/lib/kumi/core/functions/signature_resolver.rb +272 -0
- data/lib/kumi/core/ir/execution_engine/interpreter.rb +98 -7
- data/lib/kumi/core/ir/execution_engine/profiler.rb +202 -0
- data/lib/kumi/dev/ir.rb +75 -0
- data/lib/kumi/dev/parse.rb +105 -0
- data/lib/kumi/dev/runner.rb +83 -0
- data/lib/kumi/frontends/ruby.rb +28 -0
- data/lib/kumi/frontends/text.rb +46 -0
- data/lib/kumi/frontends.rb +29 -0
- data/lib/kumi/kernels/ruby/aggregate_core.rb +105 -0
- data/lib/kumi/kernels/ruby/datetime_scalar.rb +21 -0
- data/lib/kumi/kernels/ruby/mask_scalar.rb +15 -0
- data/lib/kumi/kernels/ruby/scalar_core.rb +63 -0
- data/lib/kumi/kernels/ruby/string_scalar.rb +19 -0
- data/lib/kumi/kernels/ruby/vector_struct.rb +39 -0
- data/lib/kumi/runtime/executable.rb +57 -26
- data/lib/kumi/schema.rb +4 -4
- data/lib/kumi/support/diff.rb +22 -0
- data/lib/kumi/support/ir_render.rb +61 -0
- data/lib/kumi/version.rb +1 -1
- data/lib/kumi.rb +2 -0
- data/performance_results.txt +63 -0
- data/scripts/test_mixed_nesting_performance.rb +206 -0
- metadata +45 -5
- data/docs/features/javascript-transpiler.md +0 -148
- data/lib/kumi/js.rb +0 -23
- data/lib/kumi/support/ir_dump.rb +0 -491
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec64db5a7b14df1a8656e2cedc569153a0f092d69a99544c5aa103241f61d931
|
4
|
+
data.tar.gz: 84bd4c7360eb74364e47103901fe8ccbcf6282a9cb40111d42b05357a2172c9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da7a9f3135e63779676ea5a802f48288ff2675935ab8dd8dcc751aaf309392275589f08fb92fede4dce351707369b5113e28540e5f4853629a02f4a1945ca75a
|
7
|
+
data.tar.gz: 5a45952056f81d9b4551bc7b48d3fd35c25065eb058e3cd6737879377a5c6e5f61d1cbba5b51955f54ad6ca14a797254e3381c69cd6b9eb145f3929e6e962dae
|
data/.rspec
CHANGED
data/BACKLOG.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Kumi Development Backlog
|
2
|
+
|
3
|
+
## High Priority
|
4
|
+
|
5
|
+
### RegistryV2 Migration Cleanup
|
6
|
+
- [ ] Remove legacy `lib/kumi/core/function_registry.rb` and related modules after RegistryV2 is fully integrated
|
7
|
+
- [ ] Clean up bridge code in `FunctionSignaturePass` once all functions are migrated
|
8
|
+
- [ ] Remove `create_basic_signature` fallback logic
|
9
|
+
- [ ] Update all tests to use RegistryV2 functions
|
10
|
+
|
11
|
+
## Medium Priority
|
12
|
+
|
13
|
+
### Function Registry Enhancements
|
14
|
+
- [ ] Add YAML linting for function definitions
|
15
|
+
- [ ] Implement golden-IR test fixtures for signature resolution
|
16
|
+
- [ ] Add Arrow/JS kernel mapping support
|
17
|
+
- [ ] Implement type promotion rules from YAML dtypes
|
18
|
+
|
19
|
+
### Performance Optimizations
|
20
|
+
- [ ] Cache RegistryV2 loading for repeated schema compilations
|
21
|
+
- [ ] Optimize signature resolution for large function sets
|
22
|
+
- [ ] Implement lazy loading of function kernels
|
23
|
+
|
24
|
+
## Low Priority
|
25
|
+
|
26
|
+
### Documentation
|
27
|
+
- [ ] Auto-generate function reference docs from YAML
|
28
|
+
- [ ] Add examples for each function in registry
|
29
|
+
- [ ] Document kernel implementation guidelines
|
30
|
+
|
31
|
+
### Testing
|
32
|
+
- [ ] Add comprehensive NEP-20 compliance test suite
|
33
|
+
- [ ] Stress test RegistryV2 with large function sets
|
34
|
+
- [ ] Add performance benchmarks for signature resolution
|
data/CLAUDE.md
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
# CLAUDE.md
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
!! Communication style - Write direct, factual statements. Avoid promotional language, unnecessary claims, or marketing speak. State what the system does, not what benefits it provides. Use TODOs for missing information rather than placeholder claims.
|
8
|
-
!! See all Available Functions in docs/FUNCTIONS.md
|
3
|
+
IMPORTANT!: Use `kumi parse` to see IR or Analysis States Diff - see docs/dev/parse-command.md
|
4
|
+
Remember, this gem is not on production yet, so no backward compatilibity is necessary. But do not change the public interfaces (e.g. DSL, Schema) without explicitly requested or demanded.
|
5
|
+
We are using zeitwerk, i.e.: no requires
|
6
|
+
See all Available Functions in docs/FUNCTIONS.md
|
9
7
|
|
10
8
|
## Project Overview
|
11
9
|
|
data/README.md
CHANGED
@@ -436,24 +436,6 @@ runner[:after_tax] # => 196,844.80 (cached)
|
|
436
436
|
- Sequential procedural workflows
|
437
437
|
- High-frequency processing
|
438
438
|
|
439
|
-
## JavaScript Transpiler (V 0.0.10)
|
440
|
-
Note: On the current 0.0.11 this is disabled but will be back in later versions. reason: IR/Interpreter update.
|
441
|
-
Transpiles compiled schemas to standalone JavaScript code. See [docs/features/javascript-transpiler.md](docs/features/javascript-transpiler.md) for details.
|
442
|
-
|
443
|
-
```ruby
|
444
|
-
Kumi::Js.export_to_file(FederalTax2024, "federal-tax-2024.js")
|
445
|
-
```
|
446
|
-
|
447
|
-
```javascript
|
448
|
-
const { schema } = require('./federal-tax-2024.js');
|
449
|
-
const calculator = schema.from({ income: 100_000, filing_status: "single" });
|
450
|
-
console.log(calculator.fetch('total_tax')); // 21491
|
451
|
-
```
|
452
|
-
|
453
|
-
Generated JavaScript includes only functions used by the schema.
|
454
|
-
|
455
|
-
All tests run in dual mode to verify compiled schemas produce identical results in both Ruby and JavaScript.
|
456
|
-
|
457
439
|
## Performance
|
458
440
|
|
459
441
|
Benchmarks on Linux with Ruby 3.3.8 on a Dell Latitude 7450:
|
@@ -0,0 +1,352 @@
|
|
1
|
+
# ==================== CORE - SCALAR (elementwise) ====================
|
2
|
+
|
3
|
+
- name: core.add
|
4
|
+
domain: core
|
5
|
+
opset: 1
|
6
|
+
class: scalar
|
7
|
+
summary: Numeric addition with broadcasting
|
8
|
+
signature: ["(),()->()", "(i),(i)->(i)", "(i,j),(i,j)->(i,j)"]
|
9
|
+
type_vars: {T: Numeric, U: Numeric}
|
10
|
+
dtypes: {result: "promote(T,U)", casting: "same_kind"}
|
11
|
+
null_policy: propagate
|
12
|
+
algebra: {associative: true, commutative: true, identity: 0}
|
13
|
+
vectorization: {mask_aware: true}
|
14
|
+
kernels:
|
15
|
+
- backend: ruby
|
16
|
+
impl: kumi_add
|
17
|
+
priority: 10
|
18
|
+
|
19
|
+
- name: core.sub
|
20
|
+
domain: core
|
21
|
+
opset: 1
|
22
|
+
class: scalar
|
23
|
+
signature: ["(),()->()", "(i),(i)->(i)", "(i,j),(i,j)->(i,j)"]
|
24
|
+
type_vars: {T: Numeric, U: Numeric}
|
25
|
+
dtypes: {result: "promote(T,U)", casting: "same_kind"}
|
26
|
+
null_policy: propagate
|
27
|
+
kernels:
|
28
|
+
- backend: ruby
|
29
|
+
impl: kumi_sub
|
30
|
+
priority: 10
|
31
|
+
|
32
|
+
- name: core.mul
|
33
|
+
domain: core
|
34
|
+
opset: 1
|
35
|
+
class: scalar
|
36
|
+
signature: ["(),()->()", "(i),(i)->(i)", "(i,j),(i,j)->(i,j)"]
|
37
|
+
type_vars: {T: Numeric, U: Numeric}
|
38
|
+
dtypes: {result: "promote(T,U)", casting: "same_kind"}
|
39
|
+
null_policy: propagate
|
40
|
+
algebra: {associative: true, commutative: true, identity: 1, annihilator: 0}
|
41
|
+
kernels:
|
42
|
+
- backend: ruby
|
43
|
+
impl: kumi_mul
|
44
|
+
priority: 10
|
45
|
+
|
46
|
+
- name: core.div
|
47
|
+
domain: core
|
48
|
+
opset: 1
|
49
|
+
class: scalar
|
50
|
+
signature: ["(),()->()", "(i),(i)->(i)", "(i,j),(i,j)->(i,j)"]
|
51
|
+
type_vars: {T: Numeric, U: Numeric}
|
52
|
+
dtypes: {result: "promote_float(T,U)", casting: "same_kind"}
|
53
|
+
null_policy: propagate
|
54
|
+
kernels:
|
55
|
+
- backend: ruby
|
56
|
+
impl: kumi_div
|
57
|
+
priority: 10
|
58
|
+
|
59
|
+
- name: core.eq
|
60
|
+
domain: core
|
61
|
+
opset: 1
|
62
|
+
class: scalar
|
63
|
+
signature: ["(),()->()", "(i),(i)->(i)", "(i,j),(i,j)->(i,j)"]
|
64
|
+
type_vars: {T: Any, U: Any}
|
65
|
+
dtypes: {result: "bool"}
|
66
|
+
null_policy: propagate
|
67
|
+
algebra: {idempotent: true}
|
68
|
+
kernels:
|
69
|
+
- backend: ruby
|
70
|
+
impl: kumi_eq
|
71
|
+
priority: 10
|
72
|
+
|
73
|
+
- name: core.gt
|
74
|
+
domain: core
|
75
|
+
opset: 1
|
76
|
+
class: scalar
|
77
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
78
|
+
type_vars: {T: Orderable, U: Orderable}
|
79
|
+
dtypes: {result: "bool"}
|
80
|
+
null_policy: propagate
|
81
|
+
kernels:
|
82
|
+
- backend: ruby
|
83
|
+
impl: kumi_gt
|
84
|
+
priority: 10
|
85
|
+
|
86
|
+
- name: core.gte
|
87
|
+
domain: core
|
88
|
+
opset: 1
|
89
|
+
class: scalar
|
90
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
91
|
+
type_vars: {T: Orderable, U: Orderable}
|
92
|
+
dtypes: {result: "bool"}
|
93
|
+
null_policy: propagate
|
94
|
+
kernels:
|
95
|
+
- backend: ruby
|
96
|
+
impl: kumi_gte
|
97
|
+
priority: 10
|
98
|
+
|
99
|
+
- name: core.and
|
100
|
+
domain: core
|
101
|
+
opset: 1
|
102
|
+
class: scalar
|
103
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
104
|
+
type_vars: {B1: Bool, B2: Bool}
|
105
|
+
dtypes: {result: "bool"}
|
106
|
+
null_policy: propagate
|
107
|
+
algebra: {associative: true, commutative: true, identity: true, annihilator: false}
|
108
|
+
vectorization: {short_circuit: left_to_right, mask_aware: true}
|
109
|
+
kernels:
|
110
|
+
- backend: ruby
|
111
|
+
impl: kumi_and
|
112
|
+
priority: 10
|
113
|
+
|
114
|
+
- name: core.or
|
115
|
+
domain: core
|
116
|
+
opset: 1
|
117
|
+
class: scalar
|
118
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
119
|
+
type_vars: {B1: Bool, B2: Bool}
|
120
|
+
dtypes: {result: "bool"}
|
121
|
+
null_policy: propagate
|
122
|
+
algebra: {associative: true, commutative: true, identity: false, annihilator: true}
|
123
|
+
vectorization: {short_circuit: left_to_right, mask_aware: true}
|
124
|
+
kernels:
|
125
|
+
- backend: ruby
|
126
|
+
impl: kumi_or
|
127
|
+
priority: 10
|
128
|
+
|
129
|
+
- name: core.not
|
130
|
+
domain: core
|
131
|
+
opset: 1
|
132
|
+
class: scalar
|
133
|
+
signature: ["()->()", "(i)->(i)"]
|
134
|
+
type_vars: {B: Bool}
|
135
|
+
dtypes: {result: "bool"}
|
136
|
+
null_policy: propagate
|
137
|
+
kernels:
|
138
|
+
- backend: ruby
|
139
|
+
impl: kumi_not
|
140
|
+
priority: 10
|
141
|
+
|
142
|
+
# ==================== AGGREGATES (reduce last axis in signature) ==============
|
143
|
+
|
144
|
+
- name: agg.sum
|
145
|
+
domain: core
|
146
|
+
opset: 1
|
147
|
+
class: aggregate
|
148
|
+
signature: ["(i)->()", "(i,j)->(i)"]
|
149
|
+
type_vars: {T: Numeric}
|
150
|
+
dtypes: {result: "promote(T)"}
|
151
|
+
null_policy: skip
|
152
|
+
options: {min_count: 0}
|
153
|
+
algebra: {associative: true, commutative: true, identity: 0}
|
154
|
+
kernels:
|
155
|
+
- backend: ruby
|
156
|
+
impl: kumi_sum
|
157
|
+
priority: 10
|
158
|
+
|
159
|
+
- name: agg.min
|
160
|
+
domain: core
|
161
|
+
opset: 1
|
162
|
+
class: aggregate
|
163
|
+
signature: ["(i)->()", "(i,j)->(i)"]
|
164
|
+
type_vars: {T: Orderable}
|
165
|
+
dtypes: {result: "T"}
|
166
|
+
null_policy: skip
|
167
|
+
kernels:
|
168
|
+
- backend: ruby
|
169
|
+
impl: kumi_min
|
170
|
+
priority: 10
|
171
|
+
|
172
|
+
- name: agg.max
|
173
|
+
domain: core
|
174
|
+
opset: 1
|
175
|
+
class: aggregate
|
176
|
+
signature: ["(i)->()", "(i,j)->(i)"]
|
177
|
+
type_vars: {T: Orderable}
|
178
|
+
dtypes: {result: "T"}
|
179
|
+
null_policy: skip
|
180
|
+
kernels:
|
181
|
+
- backend: ruby
|
182
|
+
impl: kumi_max
|
183
|
+
priority: 10
|
184
|
+
|
185
|
+
- name: agg.mean
|
186
|
+
domain: core
|
187
|
+
opset: 1
|
188
|
+
class: aggregate
|
189
|
+
signature: ["(i)->()", "(i,j)->(i)"]
|
190
|
+
type_vars: {T: Numeric}
|
191
|
+
dtypes: {result: "float"}
|
192
|
+
null_policy: skip
|
193
|
+
options: {min_count: 0}
|
194
|
+
kernels:
|
195
|
+
- backend: ruby
|
196
|
+
impl: kumi_mean
|
197
|
+
priority: 10
|
198
|
+
|
199
|
+
# ==================== STRUCTURE / SHAPE / JOIN ================================
|
200
|
+
|
201
|
+
- name: struct.join
|
202
|
+
domain: struct
|
203
|
+
opset: 1
|
204
|
+
class: structure
|
205
|
+
summary: Align inputs by axes using zip or product
|
206
|
+
signature: ["(i),(i)->(i)@zip", "(i),(j)->(i,j)@product"]
|
207
|
+
null_policy: error_on_missing
|
208
|
+
kernels:
|
209
|
+
- backend: ruby
|
210
|
+
impl: join_zip
|
211
|
+
when: {policy: zip}
|
212
|
+
priority: 10
|
213
|
+
- backend: ruby
|
214
|
+
impl: join_product
|
215
|
+
when: {policy: product}
|
216
|
+
priority: 10
|
217
|
+
|
218
|
+
- name: struct.align_to
|
219
|
+
domain: struct
|
220
|
+
opset: 1
|
221
|
+
class: structure
|
222
|
+
signature: ["(i)->(i)", "(i,j)->(i,j)"]
|
223
|
+
traits: {reorders: false}
|
224
|
+
null_policy: error_on_missing
|
225
|
+
kernels:
|
226
|
+
- backend: ruby
|
227
|
+
impl: align_to
|
228
|
+
priority: 10
|
229
|
+
|
230
|
+
- name: struct.lift
|
231
|
+
domain: struct
|
232
|
+
opset: 1
|
233
|
+
class: structure
|
234
|
+
signature: ["(i)->(i)", "(i,j)->(i,j)"]
|
235
|
+
summary: Group flat rows back to nested collections based on indices
|
236
|
+
kernels:
|
237
|
+
- backend: ruby
|
238
|
+
impl: lift
|
239
|
+
priority: 10
|
240
|
+
|
241
|
+
- name: struct.flatten
|
242
|
+
domain: struct
|
243
|
+
opset: 1
|
244
|
+
class: structure
|
245
|
+
signature: ["(i,j)->(k)"]
|
246
|
+
shape_fn: "flatten_axes(i,j)->k"
|
247
|
+
kernels:
|
248
|
+
- backend: ruby
|
249
|
+
impl: flatten
|
250
|
+
priority: 10
|
251
|
+
|
252
|
+
- name: struct.take
|
253
|
+
domain: struct
|
254
|
+
opset: 1
|
255
|
+
class: structure
|
256
|
+
signature: ["(i),(i)->(i)"] # take(values, indices) elemwise
|
257
|
+
type_vars: {T: Any}
|
258
|
+
dtypes: {result: "T"}
|
259
|
+
null_policy: error
|
260
|
+
kernels:
|
261
|
+
- backend: ruby
|
262
|
+
impl: take
|
263
|
+
priority: 10
|
264
|
+
|
265
|
+
- name: struct.size
|
266
|
+
domain: struct
|
267
|
+
opset: 1
|
268
|
+
class: vector
|
269
|
+
signature: ["(i)->()", "(i,j)->()"]
|
270
|
+
dtypes: {result: "int"}
|
271
|
+
null_policy: error
|
272
|
+
kernels:
|
273
|
+
- backend: ruby
|
274
|
+
impl: size
|
275
|
+
priority: 10
|
276
|
+
|
277
|
+
# ==================== MASK / CONDITIONAL ======================================
|
278
|
+
|
279
|
+
- name: mask.where
|
280
|
+
domain: mask
|
281
|
+
opset: 1
|
282
|
+
class: scalar
|
283
|
+
summary: Ternary select with broadcasting of then/else
|
284
|
+
signature:
|
285
|
+
- "(i),(i),(i)->(i)"
|
286
|
+
- "(i),(),()->(i)"
|
287
|
+
- "(),(i),()->(i)"
|
288
|
+
- "(),(),()->()"
|
289
|
+
type_vars: {B: Bool, T: Any, U: Any}
|
290
|
+
dtypes: {result: "unify(T,U)"}
|
291
|
+
null_policy: propagate
|
292
|
+
vectorization: {mask_aware: true, short_circuit: left_to_right}
|
293
|
+
kernels:
|
294
|
+
- backend: ruby
|
295
|
+
impl: where
|
296
|
+
priority: 10
|
297
|
+
|
298
|
+
# ==================== STRING (minimal) ========================================
|
299
|
+
|
300
|
+
- name: string.concat
|
301
|
+
domain: string
|
302
|
+
opset: 1
|
303
|
+
class: scalar
|
304
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
305
|
+
type_vars: {S1: String, S2: String}
|
306
|
+
dtypes: {result: "string"}
|
307
|
+
null_policy: propagate
|
308
|
+
kernels:
|
309
|
+
- backend: ruby
|
310
|
+
impl: str_concat
|
311
|
+
priority: 10
|
312
|
+
|
313
|
+
- name: string.length
|
314
|
+
domain: string
|
315
|
+
opset: 1
|
316
|
+
class: vector
|
317
|
+
signature: ["(i)->(i)", "()->()"]
|
318
|
+
type_vars: {S: String}
|
319
|
+
dtypes: {result: "int"}
|
320
|
+
null_policy: propagate
|
321
|
+
kernels:
|
322
|
+
- backend: ruby
|
323
|
+
impl: str_length
|
324
|
+
priority: 10
|
325
|
+
|
326
|
+
# ==================== DATETIME (minimal) ======================================
|
327
|
+
|
328
|
+
- name: datetime.add_days
|
329
|
+
domain: datetime
|
330
|
+
opset: 1
|
331
|
+
class: scalar
|
332
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
333
|
+
type_vars: {D: DateLike, N: IntLike}
|
334
|
+
dtypes: {result: "datetime"}
|
335
|
+
null_policy: propagate
|
336
|
+
kernels:
|
337
|
+
- backend: ruby
|
338
|
+
impl: dt_add_days
|
339
|
+
priority: 10
|
340
|
+
|
341
|
+
- name: datetime.diff_days
|
342
|
+
domain: datetime
|
343
|
+
opset: 1
|
344
|
+
class: scalar
|
345
|
+
signature: ["(),()->()", "(i),(i)->(i)"]
|
346
|
+
type_vars: {D1: DateLike, D2: DateLike}
|
347
|
+
dtypes: {result: "int"}
|
348
|
+
null_policy: propagate
|
349
|
+
kernels:
|
350
|
+
- backend: ruby
|
351
|
+
impl: dt_diff_days
|
352
|
+
priority: 10
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Analyzer Debug System
|
2
|
+
|
3
|
+
## Debug Module
|
4
|
+
|
5
|
+
**File**: `lib/kumi/core/analyzer/debug.rb`
|
6
|
+
|
7
|
+
**Enable**: `KUMI_DEBUG_STATE=1`
|
8
|
+
|
9
|
+
**Output**: JSONL to stdout with state diffs and timing per pass
|
10
|
+
|
11
|
+
**Configuration**:
|
12
|
+
- `KUMI_DEBUG_REQUIRE_FROZEN=1` - Enforce state immutability checks
|
13
|
+
|
14
|
+
## Checkpoint System
|
15
|
+
|
16
|
+
**Files**:
|
17
|
+
- `lib/kumi/core/analyzer/checkpoint.rb`
|
18
|
+
- `lib/kumi/core/analyzer/state_serde.rb`
|
19
|
+
|
20
|
+
**Enable**: `KUMI_CHECKPOINT=1`
|
21
|
+
|
22
|
+
**Configuration**:
|
23
|
+
- `KUMI_CHECKPOINT_DIR=path` - Output directory (default: `/tmp/kumi_checkpoints`)
|
24
|
+
- `KUMI_CHECKPOINT_FORMAT=marshal|json|both` - File format (default: `marshal`)
|
25
|
+
- `KUMI_CHECKPOINT_PHASE=before|after|both` - When to save (default: `both`)
|
26
|
+
|
27
|
+
**Resume/Stop**:
|
28
|
+
- `KUMI_RESUME_FROM=file.msh` - Resume from checkpoint file
|
29
|
+
- `KUMI_RESUME_AT=PassName` - Skip to specific pass
|
30
|
+
- `KUMI_STOP_AFTER=PassName` - Stop after specific pass
|
31
|
+
|
32
|
+
## Object Printers
|
33
|
+
|
34
|
+
**File**: `spec/support/debug_printers.rb`
|
35
|
+
|
36
|
+
Handles clean output for debug logs. Add new object types here when they appear as `#<Object:0x...>` in debug output.
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
```bash
|
41
|
+
# Basic debug
|
42
|
+
KUMI_DEBUG_STATE=1 bundle exec ruby script.rb
|
43
|
+
|
44
|
+
# Debug with checkpoints
|
45
|
+
KUMI_DEBUG_STATE=1 KUMI_CHECKPOINT=1 bundle exec ruby script.rb
|
46
|
+
|
47
|
+
# Resume from checkpoint
|
48
|
+
KUMI_RESUME_FROM=/tmp/kumi_checkpoints/005_TypeChecker_after.msh bundle exec ruby script.rb
|
49
|
+
|
50
|
+
# Stop at specific pass for debugging
|
51
|
+
KUMI_STOP_AFTER=BroadcastDetector bundle exec ruby script.rb
|
52
|
+
```
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Parse Command
|
2
|
+
|
3
|
+
One-command developer loop for text schemas: parse → analyze → render IR → diff.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
```bash
|
8
|
+
# Default: show diff vs golden file (or print if no golden)
|
9
|
+
kumi parse golden/simple_math/schema.kumi
|
10
|
+
|
11
|
+
# Write/overwrite golden file
|
12
|
+
kumi parse golden/simple_math/schema.kumi --write
|
13
|
+
|
14
|
+
# Update golden only if different
|
15
|
+
kumi parse golden/simple_math/schema.kumi --update
|
16
|
+
|
17
|
+
# JSON format instead of text
|
18
|
+
kumi parse golden/simple_math/schema.kumi --json --write
|
19
|
+
|
20
|
+
# Enable state tracing
|
21
|
+
kumi parse golden/simple_math/schema.kumi --trace
|
22
|
+
|
23
|
+
# Snapshot analysis passes
|
24
|
+
kumi parse golden/simple_math/schema.kumi --snap after --snap-dir debug/
|
25
|
+
```
|
26
|
+
|
27
|
+
## Exit Codes
|
28
|
+
|
29
|
+
- `0` - No changes or successful write
|
30
|
+
- `1` - Diff mismatch or analysis error
|
31
|
+
|
32
|
+
## Output
|
33
|
+
|
34
|
+
**No changes:**
|
35
|
+
```
|
36
|
+
No changes (golden/simple_math/expected/ir.txt)
|
37
|
+
```
|
38
|
+
|
39
|
+
**Diff mismatch:**
|
40
|
+
```
|
41
|
+
--- expected
|
42
|
+
+++ actual
|
43
|
+
@@ -6,7 +6,7 @@
|
44
|
+
2: map argc=2 fn=:add [0, 1]
|
45
|
+
+ 2: map argc=2 fn=:power [0, 1]
|
46
|
+
```
|
47
|
+
|
48
|
+
**Write mode:**
|
49
|
+
```
|
50
|
+
Wrote: golden/simple_math/expected/ir.txt
|
51
|
+
```
|
52
|
+
|
53
|
+
## IR Format
|
54
|
+
|
55
|
+
Deterministic text representation:
|
56
|
+
```
|
57
|
+
IR Module
|
58
|
+
decls: 3
|
59
|
+
decl[0] value:sum shape=scalar ops=4
|
60
|
+
0: load_input has_idx=false is_scalar=true plan_id=x:read scope=[] []
|
61
|
+
1: load_input has_idx=false is_scalar=true plan_id=y:read scope=[] []
|
62
|
+
2: map argc=2 fn=:add [0, 1]
|
63
|
+
3: store name=:sum [2]
|
64
|
+
```
|