use logicaffeine_compile::compile_to_rust;
const KNAPSACK: &str = r#"## To native args () -> Seq of Text
## To native parseInt (s: Text) -> Int
## Main
Let arguments be args().
Let n be parseInt(item 2 of arguments).
Let capacity be n * 5.
Let mutable weights be a new Seq of Int.
Let mutable vals be a new Seq of Int.
Let mutable i be 0.
While i is less than n:
Push (i * 17 + 3) % 50 + 1 to weights.
Push (i * 31 + 7) % 100 + 1 to vals.
Set i to i + 1.
Let cols be capacity + 1.
Let mutable prev be a new Seq of Int.
Set i to 0.
While i is less than cols:
Push 0 to prev.
Set i to i + 1.
Set i to 0.
While i is less than n:
Let mutable curr be a new Seq of Int.
Let wi be item (i + 1) of weights.
Let vi be item (i + 1) of vals.
Let mutable w be 0.
While w is at most capacity:
Let mutable best be item (w + 1) of prev.
If w is at least wi:
Let take be item (w - wi + 1) of prev + vi.
If take is greater than best:
Set best to take.
Push best to curr.
Set w to w + 1.
Set prev to curr.
Set i to i + 1.
Show item (capacity + 1) of prev.
"#;
#[test]
fn knapsack_inner_loop_is_split_into_three_for_w_loops() {
let rust = compile_to_rust(KNAPSACK).expect("knapsack compiles");
let for_w = rust.matches("for w in").count();
assert_eq!(for_w, 5, "expected versioned prefix + suffix + fallback `for w` loops:\n{rust}");
}
#[test]
fn knapsack_curr_store_is_resized_indexed_write() {
let rust = compile_to_rust(KNAPSACK).expect("knapsack compiles");
assert!(rust.contains("curr.resize("), "curr is resize-sized once:\n{rust}");
assert!(
rust.contains("curr[") || rust.contains("curr ["),
"curr is written by index:\n{rust}"
);
assert!(!rust.contains("curr.push("), "no curr.push in the split loops:\n{rust}");
}
#[test]
fn knapsack_suffix_load_is_unchecked_and_branch_free() {
let rust = compile_to_rust(KNAPSACK).expect("knapsack compiles");
assert!(
rust.contains("get_unchecked(((w - wi))"),
"suffix `prev[w-wi]` is an unchecked load:\n{rust}"
);
assert!(!rust.contains("panic_bounds_check"), "no residual bounds panics");
}