kumi 0.0.9 → 0.0.11
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 +18 -0
- data/CLAUDE.md +18 -258
- data/README.md +188 -121
- data/docs/AST.md +1 -1
- data/docs/FUNCTIONS.md +52 -8
- data/docs/VECTOR_SEMANTICS.md +286 -0
- data/docs/compiler_design_principles.md +86 -0
- data/docs/features/README.md +15 -2
- data/docs/features/hierarchical-broadcasting.md +349 -0
- data/docs/features/javascript-transpiler.md +148 -0
- data/docs/features/performance.md +1 -3
- data/docs/features/s-expression-printer.md +2 -2
- data/docs/schema_metadata.md +7 -7
- data/examples/deep_schema_compilation_and_evaluation_benchmark.rb +21 -15
- data/examples/game_of_life.rb +2 -4
- data/lib/kumi/analyzer.rb +34 -14
- data/lib/kumi/compiler.rb +4 -283
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +717 -66
- data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +1 -1
- data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +47 -0
- data/lib/kumi/core/analyzer/passes/input_collector.rb +118 -99
- data/lib/kumi/core/analyzer/passes/join_reduce_planning_pass.rb +293 -0
- data/lib/kumi/core/analyzer/passes/lower_to_ir_pass.rb +993 -0
- data/lib/kumi/core/analyzer/passes/pass_base.rb +2 -2
- data/lib/kumi/core/analyzer/passes/scope_resolution_pass.rb +346 -0
- data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +28 -0
- data/lib/kumi/core/analyzer/passes/toposorter.rb +9 -3
- data/lib/kumi/core/analyzer/passes/type_checker.rb +9 -5
- data/lib/kumi/core/analyzer/passes/type_consistency_checker.rb +2 -2
- data/lib/kumi/core/analyzer/passes/{type_inferencer.rb → type_inferencer_pass.rb} +4 -4
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +92 -48
- data/lib/kumi/core/analyzer/plans.rb +52 -0
- data/lib/kumi/core/analyzer/structs/access_plan.rb +20 -0
- data/lib/kumi/core/analyzer/structs/input_meta.rb +29 -0
- data/lib/kumi/core/compiler/access_builder.rb +36 -0
- data/lib/kumi/core/compiler/access_planner.rb +219 -0
- data/lib/kumi/core/compiler/accessors/base.rb +69 -0
- data/lib/kumi/core/compiler/accessors/each_indexed_accessor.rb +84 -0
- data/lib/kumi/core/compiler/accessors/materialize_accessor.rb +55 -0
- data/lib/kumi/core/compiler/accessors/ravel_accessor.rb +73 -0
- data/lib/kumi/core/compiler/accessors/read_accessor.rb +41 -0
- data/lib/kumi/core/compiler_base.rb +137 -0
- data/lib/kumi/core/error_reporter.rb +6 -5
- data/lib/kumi/core/errors.rb +4 -0
- data/lib/kumi/core/explain.rb +157 -205
- data/lib/kumi/core/export/node_builders.rb +2 -2
- data/lib/kumi/core/export/node_serializers.rb +1 -1
- data/lib/kumi/core/function_registry/collection_functions.rb +100 -6
- data/lib/kumi/core/function_registry/conditional_functions.rb +14 -4
- data/lib/kumi/core/function_registry/function_builder.rb +142 -53
- data/lib/kumi/core/function_registry/logical_functions.rb +173 -3
- data/lib/kumi/core/function_registry/stat_functions.rb +156 -0
- data/lib/kumi/core/function_registry.rb +138 -98
- data/lib/kumi/core/ir/execution_engine/combinators.rb +117 -0
- data/lib/kumi/core/ir/execution_engine/interpreter.rb +336 -0
- data/lib/kumi/core/ir/execution_engine/values.rb +46 -0
- data/lib/kumi/core/ir/execution_engine.rb +50 -0
- data/lib/kumi/core/ir.rb +58 -0
- data/lib/kumi/core/ruby_parser/build_context.rb +2 -2
- data/lib/kumi/core/ruby_parser/declaration_reference_proxy.rb +0 -12
- data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +37 -16
- data/lib/kumi/core/ruby_parser/input_builder.rb +61 -8
- data/lib/kumi/core/ruby_parser/parser.rb +1 -1
- data/lib/kumi/core/ruby_parser/schema_builder.rb +2 -2
- data/lib/kumi/core/ruby_parser/sugar.rb +7 -0
- data/lib/kumi/errors.rb +2 -0
- data/lib/kumi/js.rb +23 -0
- data/lib/kumi/registry.rb +17 -22
- data/lib/kumi/runtime/executable.rb +213 -0
- data/lib/kumi/schema.rb +15 -4
- data/lib/kumi/schema_metadata.rb +2 -2
- data/lib/kumi/support/ir_dump.rb +491 -0
- data/lib/kumi/support/s_expression_printer.rb +17 -16
- data/lib/kumi/syntax/array_expression.rb +6 -6
- data/lib/kumi/syntax/call_expression.rb +4 -4
- data/lib/kumi/syntax/cascade_expression.rb +4 -4
- data/lib/kumi/syntax/case_expression.rb +4 -4
- data/lib/kumi/syntax/declaration_reference.rb +4 -4
- data/lib/kumi/syntax/hash_expression.rb +4 -4
- data/lib/kumi/syntax/input_declaration.rb +6 -5
- data/lib/kumi/syntax/input_element_reference.rb +5 -5
- data/lib/kumi/syntax/input_reference.rb +5 -5
- data/lib/kumi/syntax/literal.rb +4 -4
- data/lib/kumi/syntax/location.rb +5 -0
- data/lib/kumi/syntax/node.rb +33 -34
- data/lib/kumi/syntax/root.rb +6 -6
- data/lib/kumi/syntax/trait_declaration.rb +4 -4
- data/lib/kumi/syntax/value_declaration.rb +4 -4
- data/lib/kumi/version.rb +1 -1
- data/lib/kumi.rb +6 -15
- data/scripts/analyze_broadcast_methods.rb +68 -0
- data/scripts/analyze_cascade_methods.rb +74 -0
- data/scripts/check_broadcasting_coverage.rb +51 -0
- data/scripts/find_dead_code.rb +114 -0
- metadata +36 -9
- data/docs/features/array-broadcasting.md +0 -170
- data/lib/kumi/cli.rb +0 -449
- data/lib/kumi/core/compiled_schema.rb +0 -43
- data/lib/kumi/core/evaluation_wrapper.rb +0 -40
- data/lib/kumi/core/schema_instance.rb +0 -111
- data/lib/kumi/core/vectorization_metadata.rb +0 -110
- data/migrate_to_core_iterative.rb +0 -938
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eb46e14716bf14c3d9165ffac957211f41ad5a21a74ad37c47b37c37e01b312
|
4
|
+
data.tar.gz: fd0e36d65ac41079c27cf9699a3e092ff762bc76b3af8fc90df2ec763fed3806
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54ed5e72d6acf863e0f7ed0986c8db83fab22526bcffb97b4c1b96343e724b0ae505804baed5554933c452478ced8c46ec24a6568426813e69c4007994588de6
|
7
|
+
data.tar.gz: '09aabb772643aab71d957060c934f05be5838a1056b7c635822b75759106a3119844cc7e20f96b8990ec658d969f2d2e0143ceb43d36f8d48da061c2bb80cb6a'
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
## [0.0.11] – 2025-08-13
|
2
|
+
### Added
|
3
|
+
- Intermediate Representation (IR) and slot-based VM interpreter.
|
4
|
+
- Scope-aware vector semantics (alignment, lift, hierarchical indices).
|
5
|
+
- Debug tooling: IR dump, VM/lowering traces via DEBUG_* flags.
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- Analyzer now lowers to IR via `LowerToIRPass`.
|
9
|
+
- Access modes: `:read`, `:ravel`, `:each_indexed`, `:materialize`.
|
10
|
+
|
11
|
+
### Removed (BREAKING)
|
12
|
+
- JavaScript transpiler (legacy compiler).
|
13
|
+
|
14
|
+
### Requirements
|
15
|
+
- Ruby >= 3.1 (Was >= 3.0)
|
16
|
+
|
17
|
+
### Notes
|
18
|
+
- No expected DSL changes for typical schemas; report regressions.
|
data/CLAUDE.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# CLAUDE.md
|
2
2
|
|
3
|
+
!! Important:
|
3
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.
|
4
5
|
!! We are using zeitwerk, i.e.: no requires
|
5
|
-
!!
|
6
|
-
!!
|
6
|
+
!! Disregard linting or coverage issues unless asked to do so.
|
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
|
7
9
|
|
8
10
|
## Project Overview
|
9
11
|
|
@@ -16,18 +18,13 @@ Kumi is a Declarative logic and rules engine framework with static analysis for
|
|
16
18
|
- `bundle exec rspec spec/path/to/specific_spec.rb` - Run specific test file
|
17
19
|
- `bundle exec rspec spec/path/to/specific_spec.rb:123` - Run specific test at line
|
18
20
|
|
19
|
-
### Gem Management
|
20
|
-
- `bundle install` - Install dependencies
|
21
|
-
- `gem build kumi.gemspec` - Build the gem
|
22
|
-
- `gem install ./kumi-*.gem` - Install locally built gem
|
23
|
-
|
24
21
|
## Architecture Overview
|
25
22
|
|
26
23
|
### Core Components
|
27
24
|
|
28
25
|
**Schema System** (`lib/kumi/schema.rb`):
|
29
26
|
- Entry point that ties together parsing, analysis, and compilation
|
30
|
-
-
|
27
|
+
- DSL method `schema(&block)` builds the syntax tree, runs analysis, and compiles to executable form
|
31
28
|
- Generates a `Runner` instance for executing queries against input data
|
32
29
|
|
33
30
|
**Parser** (`lib/kumi/ruby_parser{/*,.rb}`):
|
@@ -60,71 +57,18 @@ Kumi is a Declarative logic and rules engine framework with static analysis for
|
|
60
57
|
- **Pass 8**: `type_checker.rb` - Validate function types and compatibility using inferred types
|
61
58
|
|
62
59
|
**Compiler** (`lib/kumi/compiler.rb`):
|
63
|
-
-
|
60
|
+
- Compiles analyzed syntax tree into executable lambda functions
|
64
61
|
- Maps each expression type to a compilation method
|
65
62
|
- Handles function calls via `Kumi::Registry`
|
66
63
|
- Produces `CompiledSchema` with executable bindings
|
67
64
|
|
68
65
|
**Function Registry** (`lib/kumi/function_registry.rb`):
|
69
66
|
- Registry of available functions (operators, math, string, logical, collection operations)
|
70
|
-
- Supports custom function registration with
|
67
|
+
- Supports custom function registration with type metadata
|
71
68
|
- Each function includes param_types, return_type, arity, and description
|
72
69
|
- Core functions include: `==`, `>`, `<`, `add`, `multiply`, `and`, `or`, `clamp`, etc.
|
73
|
-
- Maintains backward compatibility with legacy type checking system
|
74
70
|
- Function documents are generated by the script ./scripts/generate_function_docs.rb
|
75
71
|
|
76
|
-
**Runner** (`lib/kumi/runner.rb`):
|
77
|
-
- Executes compiled schemas against input data
|
78
|
-
- Provides `fetch(key)` for individual value retrieval with caching
|
79
|
-
- Provides `slice(*keys)` for batch evaluation
|
80
|
-
- Provides `explain(key)` for detailed execution tracing
|
81
|
-
|
82
|
-
**Input Validation System** (`lib/kumi/input/` and `lib/kumi/domain/`):
|
83
|
-
- `input/validator.rb` - Main validation coordinator for type and domain checking
|
84
|
-
- `input/type_matcher.rb` - Type validation logic for primitive and complex types
|
85
|
-
- `input/violation_creator.rb` - Creates standardized violation objects with detailed messages
|
86
|
-
- `domain/validator.rb` - Domain constraint validation (ranges, arrays, procs)
|
87
|
-
- `domain/range_analyzer.rb` - Range domain analysis and validation
|
88
|
-
- `domain/enum_analyzer.rb` - Enumeration domain analysis and validation
|
89
|
-
- `domain/violation_formatter.rb` - Formats domain violation error messages
|
90
|
-
|
91
|
-
## DSL Syntax Requirements
|
92
|
-
|
93
|
-
### Critical Syntax Rules
|
94
|
-
|
95
|
-
**Module Definition Structure** (REQUIRED for CLI):
|
96
|
-
```ruby
|
97
|
-
# CORRECT - CLI can find and load this
|
98
|
-
module SchemaName
|
99
|
-
extend Kumi::Schema
|
100
|
-
|
101
|
-
schema do
|
102
|
-
# schema definition here
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# INCORRECT - CLI cannot load standalone schemas
|
107
|
-
schema do # This won't work with CLI
|
108
|
-
# schema definition
|
109
|
-
end
|
110
|
-
```
|
111
|
-
|
112
|
-
**Function Call Syntax**:
|
113
|
-
- **Symbol style**: `fn(:function_name, arg1, arg2, ...)` - The only supported function call syntax
|
114
|
-
|
115
|
-
**Arithmetic Operations**:
|
116
|
-
- **Sugar Syntax**: `input.field1 + input.field2` - Works for input fields and value references
|
117
|
-
- **Function Syntax**: `fn(:add, input.field1, input.field2)` - Always works, more explicit
|
118
|
-
- **Mixed**: Use sugar for simple operations, functions for complex ones
|
119
|
-
|
120
|
-
**Cascade Condition Syntax**:
|
121
|
-
```ruby
|
122
|
-
value :status do
|
123
|
-
on trait_name, "Result"
|
124
|
-
base "Default"
|
125
|
-
end
|
126
|
-
```
|
127
|
-
|
128
72
|
### Key Patterns
|
129
73
|
**DSL Structure**:
|
130
74
|
```ruby
|
@@ -142,38 +86,22 @@ schema do
|
|
142
86
|
string :category
|
143
87
|
end
|
144
88
|
|
145
|
-
|
146
|
-
|
147
89
|
# Fields with no declared type
|
148
90
|
any :misc_field
|
149
91
|
end
|
150
92
|
|
151
|
-
trait :name, (expression) # Boolean conditions
|
93
|
+
trait :name, (expression) # Boolean conditions
|
152
94
|
value :name, expression # Computed values
|
153
95
|
value :name do # Conditional logic
|
154
|
-
on condition, result
|
155
|
-
base default_result
|
96
|
+
on condition, result # on <trait> ?,<trait> , <expr>
|
97
|
+
base default_result # base <expr>
|
156
98
|
end
|
157
99
|
end
|
158
100
|
```
|
159
101
|
|
160
102
|
**IMPORTANT CASCADE CONDITION SYNTAX:**
|
161
103
|
In cascade expressions (`value :name do ... end`), trait references use bare identifiers:
|
162
|
-
```ruby
|
163
|
-
value :status do
|
164
|
-
on adult, "Adult Status"
|
165
|
-
on verified, "Verified User"
|
166
|
-
base "Unverified"
|
167
|
-
end
|
168
|
-
```
|
169
104
|
|
170
|
-
**Input Block System**:
|
171
|
-
- **Required**: All schemas must have an `input` block declaring expected fields
|
172
|
-
- **Type Declarations**: Preferred via type-specific methods (e.g. `integer :field`, `string :name`, `any :field` for untyped fields)
|
173
|
-
- **Complex Types**: Use helper functions: `array(:element_type)` and `hash(:key_type, :value_type)`
|
174
|
-
- **Domain Constraints**: Fields can have domains: `integer :age, domain: 18..65` (validated at runtime)
|
175
|
-
- **Field Access**: Use `input.field_name` to reference input fields in expressions
|
176
|
-
- **Separation**: Input metadata (types, domains) is separate from business logic
|
177
105
|
|
178
106
|
**Expression Types**:
|
179
107
|
- `input.field_name` - Access input data with operator methods (>=, <=, >, <, ==, !=)
|
@@ -190,86 +118,24 @@ end
|
|
190
118
|
4. Execute with Runner
|
191
119
|
|
192
120
|
**Type System** (`lib/kumi/types.rb`):
|
193
|
-
-
|
121
|
+
- Symbol-based type system
|
194
122
|
- **Dual Type System**: Declared types (from input blocks) and inferred types (from expressions)
|
195
|
-
-
|
123
|
+
- Type inference for all declarations based on expression analysis
|
196
124
|
- Type primitives: `:string`, `:integer`, `:float`, `:boolean`, `:any`, `:symbol`, `:regexp`, `:time`, `:date`, `:datetime`
|
197
125
|
- Collection types: `array(:element_type)` and `hash(:key_type, :value_type)` helper functions
|
198
|
-
- Type compatibility checking and unification algorithms for numeric types
|
199
|
-
- Enhanced error messages showing type provenance (declared vs inferred)
|
200
|
-
- Legacy compatibility constants maintained for backward compatibility
|
201
|
-
|
202
|
-
### Examples Directory
|
203
|
-
|
204
|
-
The `examples/` directory contains comprehensive examples showing Kumi usage patterns:
|
205
|
-
- `cascade_demonstration.rb` - Demonstrates cascade logic with UnsatDetector fixes (working)
|
206
|
-
- `working_comprehensive_schema.rb` - Complete feature showcase (current best practices, working)
|
207
|
-
- Mathematical predicate examples - Safe mutual recursion patterns using cascade mutual exclusion
|
208
|
-
- `federal_tax_calculator_2024.rb` - Real-world tax calculation example (working)
|
209
|
-
- `tax_2024.rb` - Simple tax example with explain functionality (working)
|
210
|
-
- `wide_schema_compilation_and_evaluation_benchmark.rb` - Performance benchmark for wide schemas (compilation and evaluation scaling)
|
211
|
-
- `deep_schema_compilation_and_evaluation_benchmark.rb` - Performance benchmark for deep dependency chains (stack-safe evaluation)
|
212
|
-
- `comprehensive_god_schema.rb` - Complex example (currently has UnsatDetector semantic errors)
|
213
|
-
|
214
|
-
*Note: Some examples may use deprecated syntax and should be updated to use the new input block system.*
|
215
|
-
|
216
|
-
## Test Structure
|
217
|
-
|
218
|
-
- `spec/kumi/` - Unit tests for core components
|
219
|
-
- `spec/integration/` - Integration tests for full workflows
|
220
|
-
- `spec/fixtures/` - Test fixtures and sample schemas
|
221
|
-
- `spec/support/` - Test helpers (`ast_factory.rb`, `schema_generator.rb`)
|
222
126
|
|
223
127
|
## Files for Understanding
|
224
128
|
|
225
129
|
. `docs/*` - Documents about Kumi, its features, DSL syntax, ...
|
226
|
-
- `examples/*` Random examples of
|
130
|
+
- `examples/*` Random examples of diverse contexts.
|
227
131
|
|
228
132
|
### Troubleshooting Schema Issues
|
229
|
-
|
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!
|
133
|
+
DEBUG, DEBUG. DEBUG LOGS!
|
234
134
|
|
235
|
-
## Input Block System Details
|
236
|
-
|
237
|
-
### Required Input Blocks
|
238
|
-
- **All schemas must have an input block** -
|
239
|
-
- Input blocks declare expected fields with optional type and domain constraints
|
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.
|
243
|
-
|
244
|
-
### Type System Integration
|
245
|
-
- **Declared Types**: Explicit type declarations in input blocks (e.g. `integer :field`, `string :name`, `any :field`)
|
246
|
-
- **Inferred Types**: Types automatically inferred from expression analysis
|
247
|
-
- **Type Checking**: Validates compatibility between declared and inferred types
|
248
|
-
- **Enhanced Errors**: Error messages show type provenance (declared vs inferred)
|
249
|
-
- **Helper Functions**: Use `array(:type)` and `hash(:key_type, :value_type)` for complex types
|
250
|
-
|
251
|
-
### Parser Components
|
252
|
-
See `lib/kumi/ruby_parser/parser.rb`
|
253
|
-
|
254
|
-
### Domain Constraints
|
255
|
-
- Can be declared: `integer :age, domain: 18..65`
|
256
|
-
- Supports Range domains (`18..65`), Array domains (`%w[active inactive]`), and Proc domains for custom validation
|
257
|
-
- Analyzer do some limited domain UNSAT detection, and its used to validated against input at Runtime
|
258
|
-
### Type Examples
|
259
|
-
```ruby
|
260
|
-
input do
|
261
|
-
string :name
|
262
|
-
integer :age, domain: 18..65
|
263
|
-
hash :metadata, key: { type: :string }, val: { type: :any }
|
264
|
-
|
265
|
-
#generic type
|
266
|
-
any :misc # this will make Kumi lose most of its analyze/inference power
|
267
|
-
end
|
268
|
-
```
|
269
135
|
|
270
136
|
### Array Broadcasting System
|
271
137
|
|
272
|
-
**
|
138
|
+
**Vectorization**: Field access on array inputs (`input.items.price`) applies operations element-wise with map/reduce detection.
|
273
139
|
|
274
140
|
**Basic Broadcasting**:
|
275
141
|
```ruby
|
@@ -278,6 +144,9 @@ input do
|
|
278
144
|
float :price
|
279
145
|
integer :quantity
|
280
146
|
string :category
|
147
|
+
array :prices do
|
148
|
+
element :integer, :val
|
149
|
+
end
|
281
150
|
end
|
282
151
|
end
|
283
152
|
|
@@ -285,112 +154,3 @@ end
|
|
285
154
|
value :subtotals, input.line_items.price * input.line_items.quantity
|
286
155
|
trait :is_taxable, (input.line_items.category != "digital")
|
287
156
|
```
|
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)
|
294
|
-
```
|
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
|
-
|
303
|
-
### Trait Syntax Evolution
|
304
|
-
|
305
|
-
**Current Syntax** (recommended):
|
306
|
-
```ruby
|
307
|
-
trait :adult, (input.age >= 18)
|
308
|
-
trait :qualified, (input.age >= 21) & (input.score > 80) & (input.verified == true)
|
309
|
-
```
|
310
|
-
|
311
|
-
**Composite Trait Syntax** (NEW - bare identifier references):
|
312
|
-
```ruby
|
313
|
-
# Base traits
|
314
|
-
trait :adult, (input.age >= 18)
|
315
|
-
trait :verified, (input.verified == true)
|
316
|
-
trait :high_score, (input.score > 80)
|
317
|
-
|
318
|
-
# Composite traits using bare identifier syntax
|
319
|
-
trait :eligible, adult & verified & high_score
|
320
|
-
trait :mixed, adult & (input.income > 50_000) & verified
|
321
|
-
|
322
|
-
# Backward compatibility - both syntaxes work together
|
323
|
-
trait :legacy_mix, adult & ref(:verified) & (input.score > 90)
|
324
|
-
```
|
325
|
-
|
326
|
-
**Deprecated Syntax** (with warnings):
|
327
|
-
```ruby
|
328
|
-
trait :adult, input.age, :>=, 18 # OLD - shows deprecation warning
|
329
|
-
trait :qualified, input.age, :>=, 21, input.score # OLD - shows deprecation warning
|
330
|
-
```
|
331
|
-
|
332
|
-
**Key Changes**:
|
333
|
-
- **NEW**: Bare identifier syntax allows direct trait reference: `adult` instead of `ref(:adult)`
|
334
|
-
- New syntax uses parenthesized expressions: `trait :name, (expression)`
|
335
|
-
- FieldRef nodes have operator methods that create CallExpression nodes
|
336
|
-
- Logical AND chaining via `&` operator (Ruby limitation prevents `&&`)
|
337
|
-
- Only AND operations supported to maintain constraint satisfaction system
|
338
|
-
- **Backward Compatible**: Both `trait_name` and `ref(:trait_name)` work together
|
339
|
-
- Old syntax maintained with deprecation warnings for backward compatibility
|
340
|
-
|
341
|
-
## Common Development Tasks
|
342
|
-
|
343
|
-
### Adding New Analyzer Passes
|
344
|
-
1. Create pass class inheriting from `PassBase` in `lib/kumi/analyzer/passes/`
|
345
|
-
2. Implement `run(errors)` method that calls `set_state(key, value)` to store results
|
346
|
-
3. Add pass to `PASSES` array in `lib/kumi/analyzer.rb` in correct order
|
347
|
-
4. Consider dependencies on other passes (e.g., TypeChecker needs TypeInferencer)
|
348
|
-
|
349
|
-
## Architecture Design Principles
|
350
|
-
|
351
|
-
- **Multi-pass Analysis**: Each analysis pass has a single responsibility and builds on previous passes
|
352
|
-
- **Immutable Syntax Tree**: AST nodes are immutable; analysis results stored separately in analyzer state
|
353
|
-
- **Dependency-driven Evaluation**: All computation follows dependency graph to ensure correct order
|
354
|
-
- **Type Safety**: Optional but comprehensive type checking without breaking existing schemas
|
355
|
-
- **Ruby Integration**: Leverages Ruby's metaprogramming while providing structured analysis
|
356
|
-
- **Unified Error Reporting**: Consistent, localized error messages throughout the system with clear interface patterns
|
357
|
-
|
358
|
-
## Code Organization Patterns
|
359
|
-
|
360
|
-
### Testing Best Practices
|
361
|
-
- **Spec Organization**: Tests organized by component with clear separation between unit and integration tests
|
362
|
-
- **Error Variable Extraction**: RSpec patterns avoid multiline block chains by extracting error variables for assertion
|
363
|
-
|
364
|
-
## Development Guides and Standards
|
365
|
-
|
366
|
-
### Error Reporting Standards
|
367
|
-
**For Parser Classes**:
|
368
|
-
```ruby
|
369
|
-
class MyParser
|
370
|
-
include ErrorReporting
|
371
|
-
|
372
|
-
def parse_something
|
373
|
-
# Immediate error raising
|
374
|
-
raise_syntax_error("Invalid syntax", location: current_location)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
```
|
378
|
-
|
379
|
-
**For Analyzer Passes**:
|
380
|
-
```ruby
|
381
|
-
class MyAnalyzerPass < PassBase
|
382
|
-
def run(errors)
|
383
|
-
# Error accumulation with enhanced location
|
384
|
-
report_error(errors, "semantic error", location: node.loc, type: :semantic)
|
385
|
-
|
386
|
-
# Backward compatible method
|
387
|
-
add_error(errors, node.loc, "legacy format error")
|
388
|
-
end
|
389
|
-
end
|
390
|
-
```
|
391
|
-
### Testing Error Scenarios
|
392
|
-
- Use `spec/integration/dsl_breakage_spec.rb` patterns for comprehensive error testing
|
393
|
-
- Use `spec/integration/potential_breakage_spec.rb` for edge cases break
|
394
|
-
- Use `spec/fixtures/location_tracking_test_schema.rb` fixture for testing different syntax error types
|
395
|
-
|
396
|
-
#
|