Skip to content

Commit cff1524

Browse files
update the code to be more generic and emit fstar code instead of pulse only syntax. I also added ensures cababilities
1 parent 47ba6f4 commit cff1524

3 files changed

Lines changed: 57 additions & 18 deletions

File tree

pulse/Pulse.Lib.C.Array.fsti

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ fn update_arr_with (#a:Type0) (arr: array a) (idx: SizeT.t) (f: (a -> a))
2020
requires with_pure (SizeT.v idx < Seq.length (value_of arr))
2121
returns _r : unit
2222
ensures live arr
23-
ensures with_pure (Seq.length (value_of arr) = old (Seq.length (value_of arr)))
23+
ensures with_pure (Seq.length (value_of arr) = old (Seq.length (value_of arr)))
24+
ensures with_pure (Seq.index (value_of arr) (SizeT.v idx) == f (old (Seq.index (value_of arr) (SizeT.v idx))))

src/pass/emit.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl NameMangling {
276276
struct Emitter<'a> {
277277
nm: NameMangling,
278278
diags: &'a mut Diagnostics,
279+
in_spec: bool,
279280
}
280281

281282
impl<'a> Emitter<'a> {
@@ -543,15 +544,36 @@ impl<'a> Emitter<'a> {
543544
}
544545
},
545546
ExprT::Index(arr, idx) => {
546-
let arr_doc = self.emit_rvalue(env, arr);
547-
let idx_doc = self.emit_rvalue(env, idx);
548-
ExprKind::RValue(annotated(
549-
v,
550-
arr_doc
551-
.append(Doc::text(".("))
552-
.append(idx_doc)
553-
.append(Doc::text(")")),
554-
))
547+
if self.in_spec {
548+
let arr_doc = self.emit_rvalue(env, arr);
549+
let idx_doc = self.emit_rvalue(env, idx);
550+
let idx_nat = match env.infer_expr(idx) {
551+
Ok(ty) if matches!(&ty.val, TypeT::SizeT) => {
552+
unaryfn(Doc::text("SizeT.v"), idx_doc)
553+
}
554+
_ => idx_doc,
555+
};
556+
ExprKind::RValue(annotated(
557+
v,
558+
parens(
559+
Doc::text("Seq.index")
560+
.append(Doc::line())
561+
.append(unaryfn(Doc::text("value_of"), arr_doc))
562+
.append(Doc::line())
563+
.append(idx_nat),
564+
),
565+
))
566+
} else {
567+
let arr_doc = self.emit_rvalue(env, arr);
568+
let idx_doc = self.emit_rvalue(env, idx);
569+
ExprKind::RValue(annotated(
570+
v,
571+
arr_doc
572+
.append(Doc::text(".("))
573+
.append(idx_doc)
574+
.append(Doc::text(")")),
575+
))
576+
}
555577
}
556578
_ => ExprKind::RValue(self.emit_rvalue_inner(env, v)),
557579
}
@@ -1189,34 +1211,41 @@ impl<'a> Emitter<'a> {
11891211
requires,
11901212
ensures,
11911213
body,
1192-
} => Doc::text("while ")
1214+
} => {
1215+
self.in_spec = true;
1216+
let inv_docs: Vec<_> = inv.iter().map(|inv| self.emit_rvalue(env, inv)).collect();
1217+
let req_docs: Vec<_> = requires.iter().map(|r| self.emit_rvalue(env, r)).collect();
1218+
let ens_docs: Vec<_> = ensures.iter().map(|e| self.emit_rvalue(env, e)).collect();
1219+
self.in_spec = false;
1220+
Doc::text("while ")
11931221
.append(parens(self.emit_rvalue(env, cond)))
11941222
.append(Doc::line())
1195-
.append(Doc::concat(inv.iter().map(|inv| {
1223+
.append(Doc::concat(inv_docs.into_iter().map(|d| {
11961224
Doc::text("invariant ")
1197-
.append(self.emit_rvalue(env, inv))
1225+
.append(d)
11981226
.group()
11991227
.nest(2)
12001228
.append(Doc::line())
12011229
})))
1202-
.append(Doc::concat(requires.iter().map(|r| {
1230+
.append(Doc::concat(req_docs.into_iter().map(|d| {
12031231
Doc::text("requires ")
1204-
.append(self.emit_rvalue(env, r))
1232+
.append(d)
12051233
.group()
12061234
.nest(2)
12071235
.append(Doc::line())
12081236
})))
1209-
.append(Doc::concat(ensures.iter().map(|e| {
1237+
.append(Doc::concat(ens_docs.into_iter().map(|d| {
12101238
Doc::text("ensures ")
1211-
.append(self.emit_rvalue(env, e))
1239+
.append(d)
12121240
.group()
12131241
.nest(2)
12141242
.append(Doc::line())
12151243
})))
12161244
.nest(2)
12171245
.append(self.emit_block(env, body))
12181246
.append(";")
1219-
.group(),
1247+
.group()
1248+
},
12201249
StmtT::Break => Doc::text("break;"),
12211250
StmtT::Continue => Doc::text("continue;"),
12221251
StmtT::Return(Some(t)) => Doc::text("return")
@@ -1745,7 +1774,9 @@ impl<'a> Emitter<'a> {
17451774
params.push(Doc::text("()"));
17461775
}
17471776

1777+
self.in_spec = true;
17481778
requires_props.extend(requires.iter().map(|r| self.emit_rvalue(env, r)));
1779+
self.in_spec = false;
17491780

17501781
let return_id = env
17511782
.push_return(ret_type.clone())
@@ -1759,7 +1790,9 @@ impl<'a> Emitter<'a> {
17591790
);
17601791
let ret_type_doc = self.emit_type(env, ret_type);
17611792

1793+
self.in_spec = true;
17621794
ensures_props.extend(ensures.iter().map(|r| self.emit_rvalue(env, r)));
1795+
self.in_spec = false;
17631796

17641797
let hdr = Doc::group(
17651798
Doc::text("fn")
@@ -2113,6 +2146,7 @@ pub fn emit(
21132146
let emitter = &mut Emitter {
21142147
nm: NameMangling::new(),
21152148
diags,
2149+
in_spec: false,
21162150
};
21172151
let mut output: Vec<Doc> = vec![];
21182152
output.push(Doc::text(format!(

test/struct_array_write.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@ struct point {
99
void set_x(_array struct point *pts, size_t i, int val)
1010
_requires(i < pts._length)
1111
_preserves_value(pts._length)
12+
_ensures(pts[i].x == val)
1213
{
1314
pts[i].x = val;
1415
}
1516

1617
void set_y(_array struct point *pts, size_t i, int val)
1718
_requires(i < pts._length)
1819
_preserves_value(pts._length)
20+
_ensures(pts[i].y == val)
1921
{
2022
pts[i].y = val;
2123
}
2224

2325
void set_both(_array struct point *pts, size_t i, int vx, int vy)
2426
_requires(i < pts._length)
2527
_preserves_value(pts._length)
28+
_ensures(pts[i].x == vx)
29+
_ensures(pts[i].y == vy)
2630
{
2731
pts[i].x = vx;
2832
pts[i].y = vy;

0 commit comments

Comments
 (0)