fix: Handle builtin out-parameter calls in RVM compiler

- Teach the hoister/destructuring planner to respect parent scope when building binding plans for extra arguments, so already-bound vars yield equality checks.
- Update the compiler’s function-call path to drop the trailing out-argument, run its binding plan after the call, and share call-target resolution logic.
- Add regression suites for builtin and user-defined out-parameter scenarios plus align the CLI example output when RVM returns undefined.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-12-02 13:29:12 -06:00
parent 5aefd51cb6
commit 30bd134a0b
5 changed files with 334 additions and 37 deletions

View File

@@ -0,0 +1,83 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# Builtin Out-Parameter Test Suite
# Verifies the compiler handles builtin return-argument syntax consistently
# across variable bindings, equality checks, scheduler ordering, and literals.
cases:
- note: builtin_out_param_simple_binding
data: {}
modules:
- |
package test
rule1 if {
floor(1.001, x)
x == 1
}
query: data.test.rule1
want_result: true
- note: builtin_out_param_scheduler_reordering
data: {}
modules:
- |
package test
rule2 if {
x == 1
floor(1.001, x)
}
query: data.test.rule2
want_result: true
- note: builtin_out_param_existing_binding_equality
data: {}
modules:
- |
package test
rule3 if {
x := 1
floor(1.001, x)
}
query: data.test.rule3
want_result: true
- note: builtin_out_param_existing_binding_mismatch
data: {}
modules:
- |
package test
rule31 if {
x := 2
floor(1.001, x)
}
query: data.test.rule31
want_result: "#undefined"
- note: builtin_out_param_literal_success
data: {}
modules:
- |
package test
rule4 if {
floor(1.001, 1)
}
query: data.test.rule4
want_result: true
- note: builtin_out_param_literal_failure
data: {}
modules:
- |
package test
rule5 if {
floor(1.001, 2)
}
query: data.test.rule5
want_result: "#undefined"

View File

@@ -0,0 +1,107 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# User-Defined Out-Parameter Test Suite
# Mirrors builtin coverage but routes through the my_floor helper rule
# to ensure planner handling stays correct for user-defined function rules.
cases:
- note: user_fcn_out_param_simple_binding
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule1 if {
my_floor(1.001, x)
x == 1
}
query: data.test.rule1
want_result: true
- note: user_fcn_out_param_scheduler_reordering
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule2 if {
x == 1
my_floor(1.001, x)
}
query: data.test.rule2
want_result: true
- note: user_fcn_out_param_existing_binding_equality
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule3 if {
x := 1
my_floor(1.001, x)
}
query: data.test.rule3
want_result: true
- note: user_fcn_out_param_existing_binding_mismatch
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule31 if {
x := 2
my_floor(1.001, x)
}
query: data.test.rule31
want_result: "#undefined"
- note: user_fcn_out_param_literal_success
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule4 if {
my_floor(1.001, 1)
}
query: data.test.rule4
want_result: true
- note: user_fcn_out_param_literal_failure
data: {}
modules:
- |
package test
my_floor(x) := y if {
floor(x, y)
}
rule5 if {
my_floor(1.001, 2)
}
query: data.test.rule5
want_result: "#undefined"