kumi 0.0.16 → 0.0.18
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 +9 -0
- data/golden/cascade_logic/schema.kumi +3 -1
- data/lib/kumi/analyzer.rb +8 -11
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +0 -81
- data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +0 -36
- data/lib/kumi/core/analyzer/passes/toposorter.rb +1 -36
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +8 -191
- data/lib/kumi/core/compiler/access_builder.rb +5 -8
- data/lib/kumi/version.rb +1 -1
- metadata +2 -25
- data/BACKLOG.md +0 -34
- data/config/functions.yaml +0 -352
- data/docs/functions/analyzer_integration.md +0 -199
- data/docs/functions/signatures.md +0 -171
- data/examples/hash_objects_demo.rb +0 -138
- data/lib/kumi/core/analyzer/passes/function_signature_pass.rb +0 -199
- data/lib/kumi/core/analyzer/passes/type_consistency_checker.rb +0 -48
- data/lib/kumi/core/functions/dimension.rb +0 -98
- data/lib/kumi/core/functions/dtypes.rb +0 -20
- data/lib/kumi/core/functions/errors.rb +0 -11
- data/lib/kumi/core/functions/kernel_adapter.rb +0 -45
- data/lib/kumi/core/functions/loader.rb +0 -119
- data/lib/kumi/core/functions/registry_v2.rb +0 -68
- data/lib/kumi/core/functions/shape.rb +0 -70
- data/lib/kumi/core/functions/signature.rb +0 -122
- data/lib/kumi/core/functions/signature_parser.rb +0 -86
- data/lib/kumi/core/functions/signature_resolver.rb +0 -272
- data/lib/kumi/kernels/ruby/aggregate_core.rb +0 -105
- data/lib/kumi/kernels/ruby/datetime_scalar.rb +0 -21
- data/lib/kumi/kernels/ruby/mask_scalar.rb +0 -15
- data/lib/kumi/kernels/ruby/scalar_core.rb +0 -63
- data/lib/kumi/kernels/ruby/string_scalar.rb +0 -19
- data/lib/kumi/kernels/ruby/vector_struct.rb +0 -39
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- André Muta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -33,13 +33,11 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- ".rspec"
|
35
35
|
- ".rubocop.yml"
|
36
|
-
- BACKLOG.md
|
37
36
|
- CHANGELOG.md
|
38
37
|
- CLAUDE.md
|
39
38
|
- LICENSE.txt
|
40
39
|
- README.md
|
41
40
|
- Rakefile
|
42
|
-
- config/functions.yaml
|
43
41
|
- docs/AST.md
|
44
42
|
- docs/DSL.md
|
45
43
|
- docs/FUNCTIONS.md
|
@@ -58,8 +56,6 @@ files:
|
|
58
56
|
- docs/features/input-declaration-system.md
|
59
57
|
- docs/features/performance.md
|
60
58
|
- docs/features/s-expression-printer.md
|
61
|
-
- docs/functions/analyzer_integration.md
|
62
|
-
- docs/functions/signatures.md
|
63
59
|
- docs/schema_metadata.md
|
64
60
|
- docs/schema_metadata/broadcasts.md
|
65
61
|
- docs/schema_metadata/cascades.md
|
@@ -72,7 +68,6 @@ files:
|
|
72
68
|
- examples/deep_schema_compilation_and_evaluation_benchmark.rb
|
73
69
|
- examples/federal_tax_calculator_2024.rb
|
74
70
|
- examples/game_of_life.rb
|
75
|
-
- examples/hash_objects_demo.rb
|
76
71
|
- examples/simple_rpg_game.rb
|
77
72
|
- examples/static_analysis_errors.rb
|
78
73
|
- examples/wide_schema_compilation_and_evaluation_benchmark.rb
|
@@ -90,7 +85,6 @@ files:
|
|
90
85
|
- lib/kumi/core/analyzer/passes/broadcast_detector.rb
|
91
86
|
- lib/kumi/core/analyzer/passes/declaration_validator.rb
|
92
87
|
- lib/kumi/core/analyzer/passes/dependency_resolver.rb
|
93
|
-
- lib/kumi/core/analyzer/passes/function_signature_pass.rb
|
94
88
|
- lib/kumi/core/analyzer/passes/input_access_planner_pass.rb
|
95
89
|
- lib/kumi/core/analyzer/passes/input_collector.rb
|
96
90
|
- lib/kumi/core/analyzer/passes/ir_dependency_pass.rb
|
@@ -104,7 +98,6 @@ files:
|
|
104
98
|
- lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb
|
105
99
|
- lib/kumi/core/analyzer/passes/toposorter.rb
|
106
100
|
- lib/kumi/core/analyzer/passes/type_checker.rb
|
107
|
-
- lib/kumi/core/analyzer/passes/type_consistency_checker.rb
|
108
101
|
- lib/kumi/core/analyzer/passes/type_inferencer_pass.rb
|
109
102
|
- lib/kumi/core/analyzer/passes/unsat_detector.rb
|
110
103
|
- lib/kumi/core/analyzer/passes/visitor_pass.rb
|
@@ -153,16 +146,6 @@ files:
|
|
153
146
|
- lib/kumi/core/function_registry/stat_functions.rb
|
154
147
|
- lib/kumi/core/function_registry/string_functions.rb
|
155
148
|
- lib/kumi/core/function_registry/type_functions.rb
|
156
|
-
- lib/kumi/core/functions/dimension.rb
|
157
|
-
- lib/kumi/core/functions/dtypes.rb
|
158
|
-
- lib/kumi/core/functions/errors.rb
|
159
|
-
- lib/kumi/core/functions/kernel_adapter.rb
|
160
|
-
- lib/kumi/core/functions/loader.rb
|
161
|
-
- lib/kumi/core/functions/registry_v2.rb
|
162
|
-
- lib/kumi/core/functions/shape.rb
|
163
|
-
- lib/kumi/core/functions/signature.rb
|
164
|
-
- lib/kumi/core/functions/signature_parser.rb
|
165
|
-
- lib/kumi/core/functions/signature_resolver.rb
|
166
149
|
- lib/kumi/core/input/type_matcher.rb
|
167
150
|
- lib/kumi/core/input/validator.rb
|
168
151
|
- lib/kumi/core/input/violation_creator.rb
|
@@ -206,12 +189,6 @@ files:
|
|
206
189
|
- lib/kumi/frontends.rb
|
207
190
|
- lib/kumi/frontends/ruby.rb
|
208
191
|
- lib/kumi/frontends/text.rb
|
209
|
-
- lib/kumi/kernels/ruby/aggregate_core.rb
|
210
|
-
- lib/kumi/kernels/ruby/datetime_scalar.rb
|
211
|
-
- lib/kumi/kernels/ruby/mask_scalar.rb
|
212
|
-
- lib/kumi/kernels/ruby/scalar_core.rb
|
213
|
-
- lib/kumi/kernels/ruby/string_scalar.rb
|
214
|
-
- lib/kumi/kernels/ruby/vector_struct.rb
|
215
192
|
- lib/kumi/registry.rb
|
216
193
|
- lib/kumi/runtime/executable.rb
|
217
194
|
- lib/kumi/runtime/run.rb
|
data/BACKLOG.md
DELETED
@@ -1,34 +0,0 @@
|
|
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/config/functions.yaml
DELETED
@@ -1,352 +0,0 @@
|
|
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
|
@@ -1,199 +0,0 @@
|
|
1
|
-
# Function Signature Analysis Integration
|
2
|
-
|
3
|
-
This document describes how NEP-20 function signatures integrate with Kumi's multi-pass analyzer architecture.
|
4
|
-
|
5
|
-
## Architecture Overview
|
6
|
-
|
7
|
-
Function signature resolution is integrated into the analyzer pipeline through a node index system that allows passes to share metadata efficiently.
|
8
|
-
|
9
|
-
```
|
10
|
-
┌─────────────────┐ ┌──────────────────────┐ ┌────────────────────┐
|
11
|
-
│ Toposorter │───▶│ FunctionSignaturePass │───▶│ LowerToIRPass │
|
12
|
-
│ Creates node │ │ Resolves signatures │ │ Validates metadata │
|
13
|
-
│ index by ID │ │ Attaches metadata │ │ Emits IR ops │
|
14
|
-
└─────────────────┘ └──────────────────────┘ └────────────────────┘
|
15
|
-
```
|
16
|
-
|
17
|
-
## Node Index System
|
18
|
-
|
19
|
-
### Creation (Toposorter)
|
20
|
-
|
21
|
-
The `Toposorter` pass creates a comprehensive index of all nodes in the AST:
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
# State structure after Toposorter
|
25
|
-
state[:node_index] = {
|
26
|
-
object_id_1 => {
|
27
|
-
node: CallExpression_instance,
|
28
|
-
type: "CallExpression",
|
29
|
-
metadata: {}
|
30
|
-
},
|
31
|
-
# ... more nodes
|
32
|
-
}
|
33
|
-
```
|
34
|
-
|
35
|
-
### Population (FunctionSignaturePass)
|
36
|
-
|
37
|
-
The `FunctionSignaturePass` populates metadata for `CallExpression` nodes:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
# After FunctionSignaturePass
|
41
|
-
entry[:metadata] = {
|
42
|
-
signature: Signature_object, # Full signature object
|
43
|
-
result_axes: [:i, :j], # Output dimension names
|
44
|
-
join_policy: :zip, # Cross-dimensional policy
|
45
|
-
dropped_axes: [:k], # Dimensions eliminated by reductions
|
46
|
-
effective_signature: { # Normalized for lowering
|
47
|
-
in_shapes: [[:i, :k], [:k, :j]],
|
48
|
-
out_shape: [:i, :j],
|
49
|
-
join_policy: :zip
|
50
|
-
},
|
51
|
-
dim_env: { i: :i, j: :j, k: :k }, # Dimension variable bindings
|
52
|
-
shape_contract: { # Simplified for lowering
|
53
|
-
in: [[:i, :k], [:k, :j]],
|
54
|
-
out: [:i, :j],
|
55
|
-
join: :zip
|
56
|
-
},
|
57
|
-
signature_score: 0 # Match quality (0 = exact)
|
58
|
-
}
|
59
|
-
```
|
60
|
-
|
61
|
-
### Consumption (LowerToIRPass)
|
62
|
-
|
63
|
-
The lowering pass validates and uses the signature metadata:
|
64
|
-
|
65
|
-
```ruby
|
66
|
-
def validate_signature_metadata(expr, entry)
|
67
|
-
node_index = get_state(:node_index)
|
68
|
-
metadata = node_index[expr.object_id][:metadata]
|
69
|
-
|
70
|
-
# Validate dropped axes for reductions
|
71
|
-
if entry&.reducer && metadata[:dropped_axes]
|
72
|
-
# Assert axis exists in scope
|
73
|
-
end
|
74
|
-
|
75
|
-
# Warn about join policies not yet implemented
|
76
|
-
if metadata[:join_policy]
|
77
|
-
# Log warning or feature flag check
|
78
|
-
end
|
79
|
-
end
|
80
|
-
```
|
81
|
-
|
82
|
-
## Pass Integration Points
|
83
|
-
|
84
|
-
### 1. Signature Resolution
|
85
|
-
|
86
|
-
**Location**: After `BroadcastDetector`, before `TypeChecker`
|
87
|
-
|
88
|
-
**Purpose**: Resolve NEP-20 signatures for all function calls
|
89
|
-
|
90
|
-
**Input**:
|
91
|
-
- Node index from Toposorter
|
92
|
-
- Broadcast metadata (optional)
|
93
|
-
- Current function registry
|
94
|
-
|
95
|
-
**Output**: Rich signature metadata attached to call nodes
|
96
|
-
|
97
|
-
### 2. Type Checking Enhancement
|
98
|
-
|
99
|
-
**Integration**: `TypeChecker` can now use signature metadata for enhanced validation:
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
def validate_function_call(node, errors)
|
103
|
-
# Get resolved signature metadata
|
104
|
-
node_entry = node_index[node.object_id]
|
105
|
-
if node_entry && node_entry[:metadata][:signature]
|
106
|
-
# Use NEP-20 signature for validation
|
107
|
-
validate_nep20_signature(node, node_entry[:metadata], errors)
|
108
|
-
else
|
109
|
-
# Fall back to legacy registry-based validation
|
110
|
-
validate_legacy_signature(node, errors)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
```
|
114
|
-
|
115
|
-
### 3. Lowering Integration
|
116
|
-
|
117
|
-
**Integration**: `LowerToIRPass` validates signature consistency and emits appropriate IR:
|
118
|
-
|
119
|
-
```ruby
|
120
|
-
when Syntax::CallExpression
|
121
|
-
entry = Kumi::Registry.entry(expr.fn_name)
|
122
|
-
validate_signature_metadata(expr, entry) # Read-only validation
|
123
|
-
|
124
|
-
# Use shape contract for IR generation
|
125
|
-
if node_entry = node_index[expr.object_id]
|
126
|
-
contract = node_entry[:metadata][:shape_contract]
|
127
|
-
# Use contract to emit appropriate reduce/join ops
|
128
|
-
end
|
129
|
-
```
|
130
|
-
|
131
|
-
## Metadata Contract
|
132
|
-
|
133
|
-
All passes can rely on this metadata structure for `CallExpression` nodes:
|
134
|
-
|
135
|
-
| Field | Type | Description |
|
136
|
-
|-------|------|-------------|
|
137
|
-
| `:signature` | `Signature` | Full signature object with dimensions |
|
138
|
-
| `:result_axes` | `Array<Symbol>` | Output dimension names |
|
139
|
-
| `:join_policy` | `Symbol?` | `:zip`, `:product`, or `nil` |
|
140
|
-
| `:dropped_axes` | `Array<Symbol>` | Dimensions eliminated (reductions) |
|
141
|
-
| `:effective_signature` | `Hash` | Normalized signature for lowering |
|
142
|
-
| `:dim_env` | `Hash` | Dimension variable bindings |
|
143
|
-
| `:shape_contract` | `Hash` | Simplified contract for IR generation |
|
144
|
-
| `:signature_score` | `Integer` | Match quality (0 = exact) |
|
145
|
-
|
146
|
-
## Error Handling
|
147
|
-
|
148
|
-
Enhanced error messages include signature information:
|
149
|
-
|
150
|
-
```ruby
|
151
|
-
# Before
|
152
|
-
"operator `multiply` expects 2 args, got 3"
|
153
|
-
|
154
|
-
# After
|
155
|
-
"Signature mismatch for `multiply` with args (i,j), (k).
|
156
|
-
Candidates: (),()->() | (i),(i)->(i).
|
157
|
-
no matching signature for shapes (i,j), (k)"
|
158
|
-
```
|
159
|
-
|
160
|
-
## Feature Flags
|
161
|
-
|
162
|
-
Control NEP-20 behavior at runtime:
|
163
|
-
|
164
|
-
```bash
|
165
|
-
export KUMI_ENABLE_FLEX=1 # Enable flexible dimension matching (?)
|
166
|
-
export KUMI_ENABLE_BCAST1=1 # Enable broadcastable matching (|1)
|
167
|
-
```
|
168
|
-
|
169
|
-
## Future Extensions
|
170
|
-
|
171
|
-
The node index architecture supports future enhancements:
|
172
|
-
|
173
|
-
### Registry V2 Integration
|
174
|
-
```ruby
|
175
|
-
# Read signatures from YAML registry
|
176
|
-
signatures = RegistryV2.get_function_signatures(node.fn_name)
|
177
|
-
```
|
178
|
-
|
179
|
-
### Type System Integration
|
180
|
-
```ruby
|
181
|
-
# Add dtype metadata alongside shape metadata
|
182
|
-
metadata[:result_dtype] = infer_result_dtype(args, signature)
|
183
|
-
```
|
184
|
-
|
185
|
-
### Optimization Metadata
|
186
|
-
```ruby
|
187
|
-
# Add optimization hints
|
188
|
-
metadata[:can_vectorize] = true
|
189
|
-
metadata[:memory_access_pattern] = :sequential
|
190
|
-
```
|
191
|
-
|
192
|
-
## Performance Considerations
|
193
|
-
|
194
|
-
- **Node index creation**: O(n) where n = total AST nodes
|
195
|
-
- **Signature resolution**: O(k*m) where k = signatures, m = arguments
|
196
|
-
- **Memory overhead**: ~100 bytes per CallExpression node
|
197
|
-
- **Pass integration**: Zero performance impact on existing passes
|
198
|
-
|
199
|
-
The architecture is designed for extensibility while maintaining backward compatibility with the existing analyzer pipeline.
|