Skip to content

Commit 50bbbce

Browse files
Merge pull request #1159 from lorchrob/array-quantifier-soundness-bug
Fix array soundness bug w/ constant inlining
2 parents bbe22cc + d28d7fb commit 50bbbce

4 files changed

Lines changed: 28 additions & 3 deletions

File tree

src/lustre/lustreAstInlineConstants.ml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ and push_pre is_guarded pos =
269269
| StructUpdate (p, e1, l, e2) -> StructUpdate (p, r e1, l, r e2)
270270
| ArrayConstr (p, e1, e2) -> ArrayConstr (p, r e1, e2)
271271
| ArrayIndex (p, e1, e2) -> ArrayIndex (p, r e1, e2)
272-
| Quantifier (p, e1, l, e2) -> Quantifier (p, e1, l, r e2)
272+
| Quantifier (p, q, l, e) -> Quantifier (p, q, l, r e)
273273
| AnyOp _ -> assert false (* desugared in lustreDesugarAnyOps *)
274274
| When _ as e -> LA.Pre (pos, e)
275275
| Condact _ as e -> LA.Pre (pos, e)
@@ -358,11 +358,21 @@ and simplify_expr ?(is_guarded = false) ctx =
358358
| Call (pos, ty_args, i, es) ->
359359
let es' = List.map (fun e -> simplify_expr ~is_guarded:false ctx e) es in
360360
Call (pos, ty_args, i, es')
361+
| Quantifier (pos, q, tis, e) ->
362+
(* 1. Don't inline constants that are shadowed by quantified vars (by removing these constants from the ctx)
363+
2. Perform inlining within tis *)
364+
let ctx, tis = List.fold_left (fun (acc_ctx, acc_tis) (p, id, ty) ->
365+
let acc_ctx = TC.remove_const acc_ctx id in
366+
let acc_ti = (p, id, inline_constants_of_lustre_type acc_ctx ty) in
367+
acc_ctx, acc_tis @ [acc_ti]
368+
) (ctx, []) tis in
369+
let e' = simplify_expr ~is_guarded:false ctx e in
370+
Quantifier (pos, q, tis, e')
361371
| e -> e
362372
(** Assumptions: These constants are arranged in dependency order,
363373
all of the constants have been type checked *)
364374

365-
let rec inline_constants_of_lustre_type ctx ty = match ty with
375+
and inline_constants_of_lustre_type ctx ty = match ty with
366376
| LA.IntRange (pos, lbound, ubound) ->
367377
let lbound' = match lbound with
368378
| None -> None
@@ -394,7 +404,8 @@ let rec inline_constants_of_lustre_type ctx ty = match ty with
394404
TArr (pos, ty1', ty2')
395405
| RefinementType (pos, (pos2, id, ty), expr) ->
396406
let ty' = inline_constants_of_lustre_type ctx ty in
397-
RefinementType (pos, (pos2, id, ty'), expr)
407+
let expr' = simplify_expr ctx expr in
408+
RefinementType (pos, (pos2, id, ty'), expr')
398409

399410
| History _ | Int _ | Bool _ | Real _
400411
| UserType _ | AbstractType _ | EnumType _ | SBitVector _ | UBitVector _ -> ty

src/lustre/typeCheckerContext.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ let add_const: tc_context -> LA.ident -> LA.expr -> tc_type -> source -> tc_cont
322322
= fun ctx i e ty sc -> {ctx with vl_ctx = IMap.add i (e, (Some ty), sc) ctx.vl_ctx}
323323
(** Adds a constant variable along with its expression and type *)
324324

325+
let remove_const: tc_context -> LA.ident -> tc_context
326+
= fun ctx i -> {ctx with vl_ctx = IMap.remove i ctx.vl_ctx}
327+
(** Removes a constant variable *)
328+
325329
let add_untyped_const : tc_context -> LA.ident -> LA.expr -> source -> tc_context
326330
= fun ctx i e sc -> {ctx with vl_ctx = IMap.add i (e, None, sc) ctx.vl_ctx}
327331

src/lustre/typeCheckerContext.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ val is_enum_variant: tc_context -> LA.ident -> bool
163163
val remove_ty: tc_context -> LA.ident -> tc_context
164164
(** Removes a type binding *)
165165

166+
val remove_const: tc_context -> LA.ident -> tc_context
167+
(** Removes a constant variable *)
168+
166169
val remove_ty_ctx: tc_context -> tc_context
167170

168171
val add_const: tc_context -> LA.ident -> LA.expr -> tc_type -> source -> tc_context
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const N: int = 3;
2+
const A : int^N = [2, 0, 3];
3+
4+
node M() returns ();
5+
let
6+
check forall (i,j:int) (0 <= i and i < N and 0 <= j and j < N) => A[i] <= A[j];
7+
tel

0 commit comments

Comments
 (0)