kumi 0.0.5 → 0.0.7
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/CLAUDE.md +76 -174
- data/README.md +205 -52
- data/{documents → docs}/AST.md +29 -29
- data/{documents → docs}/SYNTAX.md +95 -8
- data/docs/features/README.md +45 -0
- data/docs/features/analysis-cascade-mutual-exclusion.md +89 -0
- data/docs/features/analysis-type-inference.md +42 -0
- data/docs/features/analysis-unsat-detection.md +71 -0
- data/docs/features/array-broadcasting.md +170 -0
- data/docs/features/input-declaration-system.md +42 -0
- data/docs/features/performance.md +16 -0
- data/docs/schema_metadata/broadcasts.md +53 -0
- data/docs/schema_metadata/cascades.md +45 -0
- data/docs/schema_metadata/declarations.md +54 -0
- data/docs/schema_metadata/dependencies.md +57 -0
- data/docs/schema_metadata/evaluation_order.md +29 -0
- data/docs/schema_metadata/examples.md +95 -0
- data/docs/schema_metadata/inferred_types.md +46 -0
- data/docs/schema_metadata/inputs.md +86 -0
- data/docs/schema_metadata.md +108 -0
- data/examples/federal_tax_calculator_2024.rb +11 -6
- data/lib/kumi/analyzer/constant_evaluator.rb +1 -1
- data/lib/kumi/analyzer/passes/broadcast_detector.rb +246 -0
- data/lib/kumi/analyzer/passes/{definition_validator.rb → declaration_validator.rb} +4 -4
- data/lib/kumi/analyzer/passes/dependency_resolver.rb +78 -38
- data/lib/kumi/analyzer/passes/input_collector.rb +91 -30
- data/lib/kumi/analyzer/passes/name_indexer.rb +2 -2
- data/lib/kumi/analyzer/passes/pass_base.rb +1 -1
- data/lib/kumi/analyzer/passes/semantic_constraint_validator.rb +24 -25
- data/lib/kumi/analyzer/passes/toposorter.rb +44 -8
- data/lib/kumi/analyzer/passes/type_checker.rb +34 -14
- data/lib/kumi/analyzer/passes/type_consistency_checker.rb +2 -2
- data/lib/kumi/analyzer/passes/type_inferencer.rb +130 -21
- data/lib/kumi/analyzer/passes/unsat_detector.rb +134 -56
- data/lib/kumi/analyzer/passes/visitor_pass.rb +2 -2
- data/lib/kumi/analyzer.rb +16 -17
- data/lib/kumi/compiler.rb +188 -16
- data/lib/kumi/constraint_relationship_solver.rb +6 -6
- data/lib/kumi/domain/validator.rb +0 -4
- data/lib/kumi/error_reporting.rb +1 -1
- data/lib/kumi/explain.rb +32 -20
- data/lib/kumi/export/node_registry.rb +26 -12
- data/lib/kumi/export/node_serializers.rb +1 -1
- data/lib/kumi/function_registry/collection_functions.rb +14 -9
- data/lib/kumi/function_registry/function_builder.rb +4 -3
- data/lib/kumi/function_registry.rb +8 -2
- data/lib/kumi/input/type_matcher.rb +3 -0
- data/lib/kumi/input/validator.rb +0 -3
- data/lib/kumi/json_schema/generator.rb +63 -0
- data/lib/kumi/json_schema/validator.rb +25 -0
- data/lib/kumi/json_schema.rb +14 -0
- data/lib/kumi/{parser → ruby_parser}/build_context.rb +1 -1
- data/lib/kumi/ruby_parser/declaration_reference_proxy.rb +36 -0
- data/lib/kumi/{parser → ruby_parser}/dsl.rb +1 -1
- data/lib/kumi/{parser → ruby_parser}/dsl_cascade_builder.rb +5 -5
- data/lib/kumi/{parser → ruby_parser}/expression_converter.rb +20 -20
- data/lib/kumi/{parser → ruby_parser}/guard_rails.rb +1 -1
- data/lib/kumi/{parser → ruby_parser}/input_builder.rb +41 -10
- data/lib/kumi/ruby_parser/input_field_proxy.rb +46 -0
- data/lib/kumi/{parser → ruby_parser}/input_proxy.rb +4 -4
- data/lib/kumi/ruby_parser/nested_input.rb +15 -0
- data/lib/kumi/{parser → ruby_parser}/parser.rb +11 -10
- data/lib/kumi/{parser → ruby_parser}/schema_builder.rb +11 -10
- data/lib/kumi/{parser → ruby_parser}/sugar.rb +62 -10
- data/lib/kumi/ruby_parser.rb +10 -0
- data/lib/kumi/schema.rb +10 -4
- data/lib/kumi/schema_instance.rb +6 -6
- data/lib/kumi/schema_metadata.rb +524 -0
- data/lib/kumi/syntax/array_expression.rb +15 -0
- data/lib/kumi/syntax/call_expression.rb +11 -0
- data/lib/kumi/syntax/cascade_expression.rb +11 -0
- data/lib/kumi/syntax/case_expression.rb +11 -0
- data/lib/kumi/syntax/declaration_reference.rb +11 -0
- data/lib/kumi/syntax/hash_expression.rb +11 -0
- data/lib/kumi/syntax/input_declaration.rb +12 -0
- data/lib/kumi/syntax/input_element_reference.rb +12 -0
- data/lib/kumi/syntax/input_reference.rb +12 -0
- data/lib/kumi/syntax/literal.rb +11 -0
- data/lib/kumi/syntax/trait_declaration.rb +11 -0
- data/lib/kumi/syntax/value_declaration.rb +11 -0
- data/lib/kumi/vectorization_metadata.rb +108 -0
- data/lib/kumi/version.rb +1 -1
- data/lib/kumi.rb +14 -0
- metadata +55 -25
- data/lib/generators/trait_engine/templates/schema_spec.rb.erb +0 -27
- data/lib/kumi/domain.rb +0 -8
- data/lib/kumi/input.rb +0 -8
- data/lib/kumi/syntax/declarations.rb +0 -26
- data/lib/kumi/syntax/expressions.rb +0 -34
- data/lib/kumi/syntax/terminal_expressions.rb +0 -30
- data/lib/kumi/syntax.rb +0 -9
- /data/{documents → docs}/DSL.md +0 -0
- /data/{documents → docs}/FUNCTIONS.md +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec2c56684edac64e9818bbf85de98e9855c3d50df80c490c8f868b3e9b701dab
|
4
|
+
data.tar.gz: d5246f98e10b0365b47f6a67fed5c3a4cbc77d5ad15905d93b046251965135f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f71ba6867b72145247b5c1ea4c3b197f831996bf078798c6a9decdb4e047f83859e062e6a6411e2311d279f8a8cc03ca7e16ac194c9a27b84f8a55b67faa3fcb
|
7
|
+
data.tar.gz: 70c4dab6bf036da2d507f89c2d8e9d65a24da2685412d3e517a2b3c1696d200c294c512786c85bfccf9feca301e90e70a26999f5ed1528221331b55f77175c8d
|
data/CLAUDE.md
CHANGED
@@ -3,12 +3,11 @@
|
|
3
3
|
!! 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.
|
4
4
|
!! We are using zeitwerk, i.e.: no requires
|
5
5
|
!! Do not care about linter or coverage unless asked to do so.
|
6
|
-
|
7
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
6
|
+
!! IMPORTANT: 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
7
|
|
9
8
|
## Project Overview
|
10
9
|
|
11
|
-
Kumi is a
|
10
|
+
Kumi is a Declarative logic and rules engine framework with static analysis for Ruby.
|
12
11
|
|
13
12
|
## Development Commands
|
14
13
|
|
@@ -17,29 +16,11 @@ Kumi is a declarative decision-modeling compiler for Ruby that transforms comple
|
|
17
16
|
- `bundle exec rspec spec/path/to/specific_spec.rb` - Run specific test file
|
18
17
|
- `bundle exec rspec spec/path/to/specific_spec.rb:123` - Run specific test at line
|
19
18
|
|
20
|
-
### Linting & Code Quality
|
21
|
-
- `bundle exec rubocop` - Run RuboCop linter
|
22
|
-
- `bundle exec rubocop -a` - Auto-fix RuboCop issues where possible
|
23
|
-
- `rake` - Run default task (includes rspec and rubocop)
|
24
|
-
|
25
19
|
### Gem Management
|
26
20
|
- `bundle install` - Install dependencies
|
27
21
|
- `gem build kumi.gemspec` - Build the gem
|
28
22
|
- `gem install ./kumi-*.gem` - Install locally built gem
|
29
23
|
|
30
|
-
### Kumi CLI
|
31
|
-
- `./bin/kumi -i` - Start interactive REPL mode for rapid schema testing
|
32
|
-
- `./bin/kumi -f schema.rb -d data.json` - Execute schema file with input data
|
33
|
-
- `./bin/kumi -f schema.rb -k key1,key2` - Extract specific keys from schema
|
34
|
-
- `./bin/kumi -f schema.rb -e key_name` - Explain how a key is computed
|
35
|
-
- `./bin/kumi -f schema.rb -d data.json -o json` - Output results in JSON format
|
36
|
-
|
37
|
-
**CLI Features**:
|
38
|
-
- Interactive REPL with schema loading, data manipulation, and live evaluation
|
39
|
-
- File-based schema execution with JSON/YAML input data support
|
40
|
-
- Selective key extraction and explain functionality for debugging
|
41
|
-
- Multiple output formats (pretty, JSON, YAML) for integration
|
42
|
-
|
43
24
|
## Architecture Overview
|
44
25
|
|
45
26
|
### Core Components
|
@@ -49,20 +30,23 @@ Kumi is a declarative decision-modeling compiler for Ruby that transforms comple
|
|
49
30
|
- Provides the `schema(&block)` DSL method that builds the syntax tree, runs analysis, and compiles to executable form
|
50
31
|
- Generates a `Runner` instance for executing queries against input data
|
51
32
|
|
52
|
-
**Parser** (`lib/kumi/
|
53
|
-
- `dsl.rb` - Main DSL parser that converts Ruby block syntax into AST nodes
|
54
|
-
- `dsl_builder_context.rb` - Context for building DSL elements with input/value/trait methods
|
55
|
-
- `dsl_cascade_builder.rb` - Specialized builder for cascade expressions
|
56
|
-
- `dsl_proxy.rb` - Proxy object for method delegation during parsing
|
57
|
-
- `input_dsl_proxy.rb` - Proxy for input block DSL supporting both `key` method and type-specific DSL methods
|
58
|
-
- `input_proxy.rb` - Proxy for `input.field_name` references in expressions
|
33
|
+
**Parser** (`lib/kumi/ruby_parser{/*,.rb}`):
|
59
34
|
|
60
35
|
**Syntax Tree** (`lib/kumi/syntax/`):
|
61
36
|
- `node.rb` - Base node class with location tracking
|
62
37
|
- `root.rb` - Root schema node containing inputs, attributes, and traits
|
63
|
-
- `
|
64
|
-
- `
|
65
|
-
- `
|
38
|
+
- `value_declaration.rb` - Value declaration nodes (formerly Attribute)
|
39
|
+
- `trait_declaration.rb` - Trait declaration nodes (formerly Trait)
|
40
|
+
- `input_declaration.rb` - Input field declaration nodes (formerly FieldDecl)
|
41
|
+
- `call_expression.rb` - Function call expression nodes
|
42
|
+
- `array_expression.rb` - Array expression nodes (formerly ListExpression)
|
43
|
+
- `hash_expression.rb` - Hash expression nodes (for future hash literals) (currently not used)
|
44
|
+
- `cascade_expression.rb` - Cascade expression nodes (conditional values)
|
45
|
+
- `case_expression.rb` - Case expression nodes (formerly WhenCaseExpression)
|
46
|
+
- `literal.rb` - Literal value nodes
|
47
|
+
- `input_reference.rb` - Input field reference nodes (formerly FieldRef)
|
48
|
+
- `input_element_reference.rb` - Reference to nested input field (array -> obj.field)
|
49
|
+
- `declaration_reference.rb` - Declaration reference value or trait nodes
|
66
50
|
|
67
51
|
**Analyzer** (`lib/kumi/analyzer.rb`):
|
68
52
|
- Multi-pass analysis system that validates schemas and builds dependency graphs
|
@@ -126,10 +110,7 @@ end
|
|
126
110
|
```
|
127
111
|
|
128
112
|
**Function Call Syntax**:
|
129
|
-
- **Symbol style**: `fn(:function_name, arg1, arg2)` -
|
130
|
-
- **Method style**: `fn.function_name(arg1, arg2)` - Also works, more readable
|
131
|
-
- **Incorrect**: `fn()` - Empty function calls cause parse errors
|
132
|
-
- **Incorrect**: `fn.function_name()` - Empty method calls cause parse errors
|
113
|
+
- **Symbol style**: `fn(:function_name, arg1, arg2, ...)` - The only supported function call syntax
|
133
114
|
|
134
115
|
**Arithmetic Operations**:
|
135
116
|
- **Sugar Syntax**: `input.field1 + input.field2` - Works for input fields and value references
|
@@ -138,26 +119,13 @@ end
|
|
138
119
|
|
139
120
|
**Cascade Condition Syntax**:
|
140
121
|
```ruby
|
141
|
-
# CORRECT - use symbols for trait references in cascades
|
142
122
|
value :status do
|
143
123
|
on trait_name, "Result"
|
144
124
|
base "Default"
|
145
125
|
end
|
146
|
-
|
147
|
-
# INCORRECT - bare identifiers don't work in cascade conditions
|
148
|
-
value :status do
|
149
|
-
on trait_name, "Result" # This will fail
|
150
|
-
base "Default"
|
151
|
-
end
|
152
126
|
```
|
153
127
|
|
154
|
-
**UnsatDetector Considerations**:
|
155
|
-
- Cascades with mutually exclusive conditions are valid (e.g., `amount < 100` vs `amount >= 100`)
|
156
|
-
- Values that depend on such cascades are also valid (fixed in recent update)
|
157
|
-
- Use clear, non-contradictory trait names to avoid confusion
|
158
|
-
|
159
128
|
### Key Patterns
|
160
|
-
|
161
129
|
**DSL Structure**:
|
162
130
|
```ruby
|
163
131
|
schema do
|
@@ -168,6 +136,14 @@ schema do
|
|
168
136
|
array :scores, elem: { type: :float }
|
169
137
|
hash :metadata, key: { type: :string }, val: { type: :any }
|
170
138
|
|
139
|
+
array :line_items do
|
140
|
+
float :price
|
141
|
+
integer :quantity
|
142
|
+
string :category
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
|
171
147
|
# Fields with no declared type
|
172
148
|
any :misc_field
|
173
149
|
end
|
@@ -182,20 +158,13 @@ end
|
|
182
158
|
```
|
183
159
|
|
184
160
|
**IMPORTANT CASCADE CONDITION SYNTAX:**
|
185
|
-
In cascade expressions (`value :name do ... end`), trait references use
|
161
|
+
In cascade expressions (`value :name do ... end`), trait references use bare identifiers:
|
186
162
|
```ruby
|
187
163
|
value :status do
|
188
|
-
on adult, "Adult Status"
|
164
|
+
on adult, "Adult Status"
|
189
165
|
on verified, "Verified User"
|
190
166
|
base "Unverified"
|
191
167
|
end
|
192
|
-
|
193
|
-
# NOT this:
|
194
|
-
value :status do
|
195
|
-
on adult, "Adult Status" # ❌ Wrong - don't use bare identifier in cascade
|
196
|
-
on verified, "Verified User" # ❌ Wrong
|
197
|
-
base "Unverified"
|
198
|
-
end
|
199
168
|
```
|
200
169
|
|
201
170
|
**Input Block System**:
|
@@ -235,6 +204,7 @@ end
|
|
235
204
|
The `examples/` directory contains comprehensive examples showing Kumi usage patterns:
|
236
205
|
- `cascade_demonstration.rb` - Demonstrates cascade logic with UnsatDetector fixes (working)
|
237
206
|
- `working_comprehensive_schema.rb` - Complete feature showcase (current best practices, working)
|
207
|
+
- Mathematical predicate examples - Safe mutual recursion patterns using cascade mutual exclusion
|
238
208
|
- `federal_tax_calculator_2024.rb` - Real-world tax calculation example (working)
|
239
209
|
- `tax_2024.rb` - Simple tax example with explain functionality (working)
|
240
210
|
- `wide_schema_compilation_and_evaluation_benchmark.rb` - Performance benchmark for wide schemas (compilation and evaluation scaling)
|
@@ -250,70 +220,26 @@ The `examples/` directory contains comprehensive examples showing Kumi usage pat
|
|
250
220
|
- `spec/fixtures/` - Test fixtures and sample schemas
|
251
221
|
- `spec/support/` - Test helpers (`ast_factory.rb`, `schema_generator.rb`)
|
252
222
|
|
253
|
-
##
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
3. `lib/kumi/analyzer.rb` - Core analysis pipeline with multi-pass system
|
258
|
-
4. `lib/kumi/types.rb` - Static type system implementation
|
259
|
-
5. `lib/kumi/function_registry.rb` - Available functions and extension patterns
|
260
|
-
6. `lib/kumi/analyzer/passes/type_inferencer.rb` - Type inference algorithm
|
261
|
-
7. `lib/kumi/analyzer/passes/type_checker.rb` - Type validation with enhanced error messages
|
262
|
-
8. `spec/kumi/input_block_spec.rb` - Input block syntax and behavior
|
263
|
-
9. `spec/integration/compiler_integration_spec.rb` - End-to-end test examples
|
264
|
-
10. `documents/DSL.md` - Concise DSL syntax reference
|
265
|
-
11. `documents/AST.md` - AST node types and structure reference
|
266
|
-
12. `documents/SYNTAX.md` - Comprehensive sugar vs sugar-free syntax comparison with examples
|
267
|
-
13. `lib/kumi/cli.rb` - CLI implementation with REPL and file execution
|
268
|
-
14. `examples/simple_tax_schema.rb` - CLI-compatible schema example
|
269
|
-
|
270
|
-
## CLI Usage and Best Practices
|
271
|
-
|
272
|
-
### Schema File Requirements
|
273
|
-
- **Must use module structure**: `module SchemaName; extend Kumi::Schema; schema do ... end; end`
|
274
|
-
- **Must have proper require**: `require_relative "../lib/kumi"` at the top
|
275
|
-
- **Must have input block**: Even empty `input {}` blocks are required
|
276
|
-
- **Avoid inline definitions**: Don't define schemas directly in methods or blocks
|
277
|
-
|
278
|
-
### CLI Development Workflow
|
279
|
-
1. **Start with REPL**: Use `./bin/kumi -i` for rapid prototyping and testing
|
280
|
-
2. **Test with files**: Create `.rb` schema files and `.json/.yaml` data files
|
281
|
-
3. **Iterate quickly**: Use `-k key1,key2` to focus on specific outputs
|
282
|
-
4. **Debug with explain**: Use `-e key_name` to understand computation flow
|
283
|
-
5. **Validate with different data**: Test edge cases with varied input data
|
284
|
-
|
285
|
-
### Common CLI Patterns
|
286
|
-
```bash
|
287
|
-
# Interactive development
|
288
|
-
./bin/kumi -i
|
289
|
-
kumi> schema examples/my_schema.rb
|
290
|
-
kumi> data test_data.json
|
291
|
-
kumi> get result
|
292
|
-
|
293
|
-
# File-based execution
|
294
|
-
./bin/kumi -f examples/tax_schema.rb -d examples/tax_data.json -k total_tax,effective_rate
|
295
|
-
|
296
|
-
# Debugging computations
|
297
|
-
./bin/kumi -f examples/complex_schema.rb -d examples/data.json -e complex_calculation
|
298
|
-
|
299
|
-
# Output formats for integration
|
300
|
-
./bin/kumi -f schema.rb -d data.json -k results -o json | jq '.results'
|
301
|
-
```
|
223
|
+
## Files for Understanding
|
224
|
+
|
225
|
+
. `docs/*` - Documents about Kumi, its features, DSL syntax, ...
|
226
|
+
- `examples/*` Random examples of very diverse contexts.
|
302
227
|
|
303
228
|
### Troubleshooting Schema Issues
|
304
229
|
- **Parse Errors**: Check function syntax (avoid empty `fn()` calls)
|
305
|
-
- **Module Not Found**: Ensure proper module structure and naming
|
306
|
-
- **UnsatDetector Errors**: Review trait logic for contradictions
|
307
|
-
- **Type Errors**: Check input block type declarations match usage
|
308
|
-
- **Runtime Errors**: Use explain to trace computation dependencies
|
230
|
+
- **Module Not Found**: Ensure proper module structure and naming, see examples
|
231
|
+
- **UnsatDetector Errors**: Review trait logic for contradictions, add debugs!
|
232
|
+
- **Type Errors**: Check input block type declarations match usage, add debugs!
|
233
|
+
- **Runtime Errors**: Use explain to trace computation dependencies, add debugs!
|
309
234
|
|
310
235
|
## Input Block System Details
|
311
236
|
|
312
237
|
### Required Input Blocks
|
313
|
-
- **All schemas must have an input block** -
|
238
|
+
- **All schemas must have an input block** -
|
314
239
|
- Input blocks declare expected fields with optional type and domain constraints
|
315
|
-
- **Empty input blocks are allowed**
|
316
|
-
- Fields are accessed via `input.field_name`
|
240
|
+
- **Empty input blocks are allowed** -`input {}` Even if its not very useful.
|
241
|
+
- Fields are accessed via `input.field_name` or `input.field.nested_field.nested_nested_field` which
|
242
|
+
works for referencing nested array input declarations.
|
317
243
|
|
318
244
|
### Type System Integration
|
319
245
|
- **Declared Types**: Explicit type declarations in input blocks (e.g. `integer :field`, `string :name`, `any :field`)
|
@@ -323,29 +249,57 @@ kumi> get result
|
|
323
249
|
- **Helper Functions**: Use `array(:type)` and `hash(:key_type, :value_type)` for complex types
|
324
250
|
|
325
251
|
### Parser Components
|
326
|
-
|
327
|
-
- `input_proxy.rb` - Handles `input.field_name` references in expressions
|
328
|
-
- `input_collector.rb` - Collects and validates field metadata consistency
|
252
|
+
See `lib/kumi/ruby_parser/parser.rb`
|
329
253
|
|
330
254
|
### Domain Constraints
|
331
255
|
- Can be declared: `integer :age, domain: 18..65`
|
332
|
-
- **Implemented**: Domain validation is active and enforced at runtime
|
333
256
|
- Supports Range domains (`18..65`), Array domains (`%w[active inactive]`), and Proc domains for custom validation
|
334
|
-
-
|
335
|
-
|
257
|
+
- Analyzer do some limited domain UNSAT detection, and its used to validated against input at Runtime
|
336
258
|
### Type Examples
|
337
259
|
```ruby
|
338
260
|
input do
|
339
|
-
# New type-specific DSL methods (recommended)
|
340
261
|
string :name
|
341
262
|
integer :age, domain: 18..65
|
342
263
|
hash :metadata, key: { type: :string }, val: { type: :any }
|
343
264
|
|
344
|
-
#
|
345
|
-
any :misc
|
265
|
+
#generic type
|
266
|
+
any :misc # this will make Kumi lose most of its analyze/inference power
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
### Array Broadcasting System
|
271
|
+
|
272
|
+
**Automatic Vectorization**: Field access on array inputs (`input.items.price`) applies operations element-wise with intelligent map/reduce detection.
|
273
|
+
|
274
|
+
**Basic Broadcasting**:
|
275
|
+
```ruby
|
276
|
+
input do
|
277
|
+
array :line_items do
|
278
|
+
float :price
|
279
|
+
integer :quantity
|
280
|
+
string :category
|
281
|
+
end
|
346
282
|
end
|
283
|
+
|
284
|
+
# Element-wise computation - broadcasts over each item
|
285
|
+
value :subtotals, input.line_items.price * input.line_items.quantity
|
286
|
+
trait :is_taxable, (input.line_items.category != "digital")
|
287
|
+
```
|
288
|
+
|
289
|
+
**Aggregation Operations**: Functions consuming arrays automatically detected:
|
290
|
+
```ruby
|
291
|
+
value :total_subtotal, fn(:sum, subtotals)
|
292
|
+
value :avg_price, fn(:avg, input.line_items.price)
|
293
|
+
value :max_quantity, fn(:max, input.line_items.quantity)
|
347
294
|
```
|
348
295
|
|
296
|
+
**Implementation Components**:
|
297
|
+
- **InputElementReference** AST nodes for nested field access paths
|
298
|
+
- **BroadcastDetector** analyzer pass identifies vectorized vs scalar operations
|
299
|
+
- **Compiler** generates appropriate map/reduce functions based on usage context
|
300
|
+
- **Type Inference** automatically infers types for array element operations
|
301
|
+
- Supports arbitrary depth field access with nested arrays and hashes
|
302
|
+
|
349
303
|
### Trait Syntax Evolution
|
350
304
|
|
351
305
|
**Current Syntax** (recommended):
|
@@ -392,59 +346,20 @@ trait :qualified, input.age, :>=, 21, input.score # OLD - shows deprecation war
|
|
392
346
|
3. Add pass to `PASSES` array in `lib/kumi/analyzer.rb` in correct order
|
393
347
|
4. Consider dependencies on other passes (e.g., TypeChecker needs TypeInferencer)
|
394
348
|
|
395
|
-
### Working with AST Nodes
|
396
|
-
- All nodes include `Node` module for location tracking
|
397
|
-
- Use `spec/support/ast_factory.rb` helpers in tests
|
398
|
-
- Field declarations use `FieldDecl` nodes with name, domain, and type
|
399
|
-
- Field references use `FieldRef` nodes (from `input.field_name`) with operator methods
|
400
|
-
- FieldRef operator methods (>=, <=, >, <, ==, !=) create CallExpression nodes
|
401
|
-
- CallExpression `&` method enables logical AND chaining
|
402
|
-
|
403
|
-
### Testing Input Block Features
|
404
|
-
- See `spec/kumi/input_block_spec.rb` for comprehensive input block tests
|
405
|
-
- Use `schema_generator.rb` helper for creating test schemas
|
406
|
-
- All integration tests now require input blocks
|
407
|
-
|
408
349
|
## Architecture Design Principles
|
409
350
|
|
410
351
|
- **Multi-pass Analysis**: Each analysis pass has a single responsibility and builds on previous passes
|
411
352
|
- **Immutable Syntax Tree**: AST nodes are immutable; analysis results stored separately in analyzer state
|
412
353
|
- **Dependency-driven Evaluation**: All computation follows dependency graph to ensure correct order
|
413
354
|
- **Type Safety**: Optional but comprehensive type checking without breaking existing schemas
|
414
|
-
- **Backward Compatibility**: New features maintain compatibility with existing DSL and APIs
|
415
355
|
- **Ruby Integration**: Leverages Ruby's metaprogramming while providing structured analysis
|
416
|
-
- **Separation of Concerns**: Input metadata (types, domains) separated from business logic
|
417
|
-
- **Class Decomposition**: Large classes split into focused, single-responsibility components following RuboCop guidelines
|
418
|
-
- **Delegation Pattern**: Complex operations delegated to specialized analyzer and formatter classes
|
419
356
|
- **Unified Error Reporting**: Consistent, localized error messages throughout the system with clear interface patterns
|
420
357
|
|
421
358
|
## Code Organization Patterns
|
422
359
|
|
423
|
-
### Modular Validation Architecture
|
424
|
-
- **Coordinator Classes**: Main classes like `Input::Validator` and `Domain::Validator` coordinate but delegate complex logic
|
425
|
-
- **Specialized Analyzers**: Domain-specific classes like `RangeAnalyzer` and `EnumAnalyzer` handle specific constraint types
|
426
|
-
- **Formatter Classes**: Dedicated classes like `ViolationFormatter` handle message formatting with consistent patterns
|
427
|
-
- **Creator Classes**: Classes like `ViolationCreator` centralize object creation with standardized structure
|
428
|
-
|
429
360
|
### Testing Best Practices
|
430
361
|
- **Spec Organization**: Tests organized by component with clear separation between unit and integration tests
|
431
362
|
- **Error Variable Extraction**: RSpec patterns avoid multiline block chains by extracting error variables for assertion
|
432
|
-
- **Shared Contexts**: Use `schema_generator` and other shared contexts for consistent test setup
|
433
|
-
|
434
|
-
### RuboCop Compliance
|
435
|
-
- **Method Length**: Keep methods under 10 lines through extraction and delegation
|
436
|
-
- **Class Length**: Break classes over 100 lines into focused components
|
437
|
-
- **Complexity Metrics**: Reduce cyclomatic and ABC complexity through single-responsibility design
|
438
|
-
- **Style Consistency**: Follow Ruby style guidelines for readability and maintainability
|
439
|
-
|
440
|
-
### Error Reporting Architecture
|
441
|
-
- **Unified Interface**: Use `ErrorReporter` module and `ErrorReporting` mixin for consistent error handling
|
442
|
-
- **Location Information**: All errors must include proper file:line:column location data
|
443
|
-
- **Precise Location Tracking**: Error objects preserve location data in `.location` attribute for programmatic access
|
444
|
-
- **User Code Location**: Errors point to actual user DSL code, not internal library files
|
445
|
-
- **Backward Compatibility**: Support both legacy `[location, message]` and new `ErrorEntry` formats
|
446
|
-
- **Type Categorization**: Errors categorized as `:syntax`, `:semantic`, `:type`, `:runtime`
|
447
|
-
- **Enhanced Messaging**: Support for error suggestions, context, and similar name detection
|
448
363
|
|
449
364
|
## Development Guides and Standards
|
450
365
|
|
@@ -477,18 +392,5 @@ end
|
|
477
392
|
- Use `spec/integration/dsl_breakage_spec.rb` patterns for comprehensive error testing
|
478
393
|
- Use `spec/integration/potential_breakage_spec.rb` for edge cases break
|
479
394
|
- Use `spec/fixtures/location_tracking_test_schema.rb` fixture for testing different syntax error types
|
480
|
-
- Test backward compatibility with existing analyzer pass specs
|
481
|
-
|
482
|
-
### Key Development Files
|
483
|
-
12. `lib/kumi/error_reporter.rb` - Central error reporting functionality
|
484
|
-
13. `lib/kumi/error_reporting.rb` - Mixin for consistent error interfaces
|
485
|
-
14. `spec/integration/location_tracking_spec.rb` - Comprehensive tests for error location accuracy
|
486
|
-
15. `spec/fixtures/location_tracking_test_schema.rb` - Fixture with intentional syntax errors for location testing
|
487
|
-
16. `ERROR_REPORTING_INTERFACE.md` - Detailed error reporting implementation guide
|
488
|
-
17. `ON_ERRORS.md` - Comprehensive analysis of DSL breakage scenarios and error quality
|
489
|
-
18. `spec/integration/dsl_breakage_spec.rb` - Integration tests for all DSL breakage scenarios
|
490
|
-
19. `spec/integration/potential_breakage_spec.rb` - Edge cases that should break but might not
|
491
|
-
20. `docs/development/README.md` - Development guides directory index
|
492
|
-
21. `docs/development/error-reporting.md` - Comprehensive error reporting standards and patterns
|
493
395
|
|
494
396
|
#
|