early return (#189)

If a rule is written to produce a constant value, then not all iterations of loops
within it need to be executed. Execution can stop via early return once the first iteration
that produces a value has been executed.

This brings forth the question : What if one of the subsequent iterations would have resulted
in an error?
e.g:
x {
  [1, "hello"][_] + 1
}

Such errors are not raised; consistent with OPA.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2024-04-22 07:41:35 -07:00
committed by GitHub
parent de56cce7cb
commit 316f3a7692
6 changed files with 184 additions and 12 deletions

View File

@@ -92,10 +92,10 @@ fn run_aci_tests(dir: &Path) -> Result<()> {
Ok(actual) => {
println!(
"DIFF {}",
colored_diff::PrettyDifference {
expected: &serde_yaml::to_string(&case.want_result)?,
actual: &serde_yaml::to_string(&actual)?
}
prettydiff::diff_chars(
&serde_yaml::to_string(&case.want_result)?,
&serde_yaml::to_string(&actual)?
)
);
nfailures += 1;

View File

@@ -21,3 +21,87 @@ cases:
x1: [[1, 0], [2, 1], [3, 2], [4, 3]]
x2: [[1, 1], [2, 2], [3, 3], [4, 4]]
x3: [["q", "p"], ["s", "r"]]
- note: early return
data: {}
modules:
- |
package test
import future.keywords
a = [1, "hello"]
# Implicit value
b1 {
a[_] + 1
}
# Literals
b2 := true { a[_] + 1 }
b3 := false { a[_] + 1 }
b4 := 1 { a[_] + 1 }
b5 := null { a[_] + 1 }
b6 := "hello" { a[_] + 1 }
b7 := `world` { a[_] + 1 }
# constant refs
c[null] := true { a[_] + 1 }
c["hello"] := false { a[_] + 1 }
c[`world`] := 1 { a[_] + 1 }
c[true] := null { a[_] + 1 }
c[false] := "hello" { a[_] + 1 }
c[7] := `world` { a[_] + 1 }
# Old style set must should also be considered for early return.
old.style { a[_] + 1 }
# Multi part constant refactor
multi[1]["hello"] := 5 { a[_] +1 }
# Two elements must be produced
d = [1 | [1,2][_] ]
# Non simple ref must not result in early return.
f[p] = 5 {
p := a[_]
}
f1[p] = 5 {
a[p]
}
# Contains syntax
g contains p if {
p := a[_]
}
query: data.test
want_result:
a: [1, "hello"]
b1: true
b2: true
b3: false
b4: 1
b5: null
b6: "hello"
b7: "world"
c:
null: true
"hello": false
"world": 1
true: null
false: "hello"
7: "world"
d: [1, 1]
f:
1: 5
"hello": 5
f1:
0: 5
1: 5
g:
set!: [1, "hello"]
multi:
1:
"hello": 5
old:
set!: ["style"]