Skip to content

Commit 5c59b37

Browse files
committed
Fix loop variant implementation and adjust tests
1 parent 41ff733 commit 5c59b37

File tree

3 files changed

+24
-30
lines changed

3 files changed

+24
-30
lines changed

src/lib.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,16 @@ fn return_to_ivl(expr: Option<&Expr>, span: &Span, method_context: &MethodContex
853853

854854
fn loop_to_ivl(invariants: &Vec<Expr>, variant: &Option<Expr>, cases: &Cases, method_context: &MethodContext) -> Result<IVLCmd, Error> {
855855
let mut result = IVLCmd::assert(&Expr::new_typed(ExprKind::Bool(true), Type::Bool), "Please don't fail!");
856+
857+
match variant {
858+
Some(variant_expr) => {
859+
let mut variant_entry_assertion = IVLCmd::assert(&Expr::op(variant_expr, Op::Ge, &Expr::num(0)), "Loop variant might not be non-negative on entry");
860+
variant_entry_assertion.span = variant_expr.span;
861+
result = result.seq(&variant_entry_assertion);
862+
}
863+
_ => {}
864+
}
865+
856866
let mut loop_invariants_assertions: Vec<(Expr, Expr)> = Vec::new();
857867
for invariant in invariants {
858868
let expr_without_broke = replace_broke_in_expression(invariant, false);
@@ -878,9 +888,7 @@ fn loop_to_ivl(invariants: &Vec<Expr>, variant: &Option<Expr>, cases: &Cases, me
878888
Some(variant_expr) => {
879889
let variant_name = get_fresh_var_name(&Ident(String::from("variant")));
880890
let variant_assignment = IVLCmd::assign(&Name { span: variant_expr.span, ident: variant_name.clone() }, variant_expr);
881-
let mut variant_base = Expr::new_typed(ExprKind::Infix(Box::new(Expr::ident(&variant_name.clone(), &Type::Int)), Op::Ge, Box::new(Expr::num(0))), Type::Bool);
882-
variant_base.span = variant_expr.span.clone();
883-
result = result.seq(&variant_assignment).seq(&IVLCmd::assert(&variant_base, "Loop variant might not be non-negative on entry"));
891+
result = result.seq(&variant_assignment);
884892
&Expr::new_typed(ExprKind::Infix(Box::new(variant_expr.clone()), Op::Lt, Box::new(Expr::ident(&variant_name, &Type::Int))), Type::Bool)
885893
},
886894
_ => &Expr::new_typed(ExprKind::Bool(true), Type::Bool)

tests/loop-decrease-bad.slang

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
method sumn(n: Int): Int
1+
method client(n: Int)
22
requires n >= 0
3-
ensures result == n * (n + 1)/2
43
{
5-
var acc: Int := 0;
4+
var counter: Int := n;
65
var i: Int := 0;
7-
loop
8-
invariant i >= 0
9-
invariant i <= n
10-
invariant acc == i * (i + 1) / 2
11-
// CheckError
12-
decreases n + i
6+
var j: Int := 0;
7+
loop
8+
decreases counter + j
139
{
10+
i == 10 && n >= 20 =>
11+
counter := counter - 10;
12+
i := i + 10,
1413
// @CheckError
15-
i < n =>
16-
i := i + 1;
17-
acc := acc + i
18-
};
19-
assert i == n;
20-
return acc
14+
i < n && i >= 0 =>
15+
counter := counter - 1;
16+
j := j + 1;
17+
i := i + 1
18+
}
2119
}

tests/loop-decreases-forever-bad.slang

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)