Conversation
hadrienk
left a comment
There was a problem hiding this comment.
Few comments here and there. Given the scope, I'd question the LLM about how can we control the base implementation and validate the new UdoFunctionExpression and wiring until we know it works. Ie: unit tests on the model first with hard coded udo we replace later by dynamically resolved instances.
| **Source of truth:** engine-side `UdoDefinition` in `ENGINE_SCOPE` bindings. | ||
| **Dispatch hook:** trampoline `java.lang.reflect.Method` registered under the same name (not a second source of truth). | ||
|
|
||
| No `vtl-model` DTO in P0. |
There was a problem hiding this comment.
Because the body is an ANTLR ExprContext (and we keep an engine handle for re-entry). That would pull the parser into vtl-model. Same as rulesets: engine-side artefact in bindings. Clarified in ffd5f0d.
|
|
||
| ## Body representation | ||
|
|
||
| **Parse subtree** (`ExprContext`). Define does not evaluate the body. Invoke re-enters `ExpressionVisitor` with a child map (params + outer bindings). Free vars resolve at **invoke time** ([08 §1](./08-open-questions.md)). |
There was a problem hiding this comment.
Names in the body that aren’t parameters (e.g. y in max_with_y). P0 looks them up at invoke time; params shadow outer names. Not a lexical closure — snapshot-at-define can come later. Clarified in ffd5f0d.
| | Action | Why | | ||
| |--------|-----| | ||
| | `bindings.put(name, udo)` | Source of truth for invoke | | ||
| | `registerMethod(name, trampoline)` | Enables `FunctionExpression` / `Method.invoke` path | |
There was a problem hiding this comment.
Not sure. Might need to "resolve" the function id (like a variable) and then call it.
There was a problem hiding this comment.
Registering the method with registerMethod goes around the bindings and make closure scoping moot.
|
|
||
| ```java | ||
| String name = ctx.operatorID().getText(); | ||
| Object binding = engine.getBindings(ENGINE_SCOPE).get(name); |
There was a problem hiding this comment.
Might need to check what the scope mechanisms gives us here. Maybe create a scoped view of the bindings.
There was a problem hiding this comment.
Yes. Call lookup uses the visitor map, not always ENGINE_SCOPE (8dcae61). P0 is still invoke-time free-var lookup, not a snapshot at define.
| 5. If `returns` declared → assignability check (`integer` ⊆ `number` allowed). | ||
| 6. Return result. | ||
|
|
||
| ThreadLocal CallSite is the P0 bridge (no per-UDO bytecode). Acceptable for the locked pattern; replace later only if needed. |
There was a problem hiding this comment.
Double check later feasibility
| | scalar actual → opaque `dataset` formal | **reject** | | ||
| | opaque `dataset` ↔ opaque `dataset` | allow (`instanceof Dataset` / `DatasetExpression`) | | ||
|
|
||
| Do not invent a parallel assignability table for UDOs. |
There was a problem hiding this comment.
Probably the most important. Not sure about the value of this file. We have a type system, it will probably just work. Ask LLM about potential changes it foresees.
There was a problem hiding this comment.
Agree, no parallel type system. 06 is now only which signature syntax we reject at define (component, constraints, …). Assignability should follow existing TypeChecking (ffd5f0d). Not recoding that in this pass.
There was a problem hiding this comment.
I'd put that as the first step. Absolute requirement.
There was a problem hiding this comment.
Needs more work. Maybe leverage the plan in prov? Tests written in vtl itself + unit testing at the engine level?
There was a problem hiding this comment.
Yes. Hardcoded expression unit tests first (02a258b), plus the existing script-level UserDefinedOperatorTest. .vtl fixtures like the prov corpus can come later, not blocking this PR.
| | Tag | IDs | | ||
| |-----|-----| | ||
| | Doc | D1–D4 | | ||
| | Métier | DS1–DS5 | |
There was a problem hiding this comment.
Fixed in ffd5f0d — “Métier” → “Recipes”.
|
|
||
| ## 7. Component-level calls | ||
|
|
||
| Commented grammar (`genericOperatorsComponent` / `callComponent`) suggests component-level UDO invoke is unfinished upstream. **Out of scope** until grammar is revived. |
There was a problem hiding this comment.
Make sure to implement so that it work when compExpr is removed from grammar.
There was a problem hiding this comment.
UDO calls go through the normal expression path (visitCallDataset / ResolvableExpression), not callComponent (already commented out in Vtl.g4). 08 rephrased in ffd5f0d.
| * Resolves call-site arguments (defaults / {@code _}) then returns a {@link UdoFunctionExpression} | ||
| * so evaluation goes through {@code FunctionExpression} → {@code Method.invoke}. | ||
| */ | ||
| public final class UdoInvokeExecutor { |
There was a problem hiding this comment.
Weird. With the resolvable expr this should be simpler. It should also implement the general expression contract.
No description provided.