Skip to content

Commit d8fca33

Browse files
committed
feat(hax-lib&backend): F*: support for SMT patterns
1 parent e8b4386 commit d8fca33

8 files changed

Lines changed: 46 additions & 8 deletions

File tree

engine/backends/fstar/fstar_backend.ml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ struct
897897
>> Option.value ~default:Fn.id map_expr
898898
>> pexpr >> f >> F.term)
899899
in
900-
let decreases =
900+
let extract_any_to_unit_payload =
901901
let visitor =
902902
object
903903
inherit [_] U.Visitors.map as super
@@ -910,9 +910,18 @@ struct
910910
| _ -> super#visit_expr () e
911911
end
912912
in
913-
attr_term Decreases ~map_expr:(visitor#visit_expr ()) (fun t ->
913+
visitor#visit_expr ()
914+
in
915+
let decreases =
916+
attr_term Decreases ~map_expr:extract_any_to_unit_payload (fun t ->
914917
F.AST.Decreases (t, None))
915918
in
919+
let smtpat =
920+
let smt_pat = F.term_of_lid [ "SMTPat" ] in
921+
attr_term SMTPat ~map_expr:extract_any_to_unit_payload (fun t ->
922+
let payload = F.mk_e_app smt_pat [ t ] in
923+
(F.AST.mkConsList F.dummyRange [ payload ]).tm)
924+
in
916925
let is_lemma = Attrs.lemma attrs in
917926
let prepost_bundle =
918927
let trivial_pre = F.term_of_lid [ "Prims"; "l_True" ] in
@@ -935,7 +944,7 @@ struct
935944
let args =
936945
(Option.map ~f:(fun (req, ens) -> [ req; ens ]) prepost_bundle
937946
|> Option.value ~default:[])
938-
@ Option.to_list decreases
947+
@ Option.to_list decreases @ Option.to_list smtpat
939948
in
940949
match args with
941950
| [] -> typ

engine/lib/attr_payloads.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ module AssocRole = struct
6363
| Requires
6464
| Ensures
6565
| Decreases
66+
| SMTPat
6667
| Refine
6768
| ProcessRead
6869
| ProcessWrite
@@ -84,6 +85,7 @@ module AssocRole = struct
8485
| Requires -> Requires
8586
| Ensures -> Ensures
8687
| Decreases -> Decreases
88+
| SMTPat -> SMTPat
8789
| Refine -> Refine
8890
| ItemQuote -> ItemQuote
8991
| ProcessRead -> ProcessRead

hax-lib/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::path::Path;
55
const FSTAR_EXTRA: &str = r"
66
pub use hax_lib_macros::fstar_options as options;
77
pub use hax_lib_macros::fstar_verification_status as verification_status;
8+
pub use hax_lib_macros::fstar_smt_pat as smt_pat;
89
";
910

1011
fn main() {

hax-lib/macros/src/dummy.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ identity_proc_macro_attribute!(
4646
fstar_after,
4747
coq_after,
4848
proverif_after,
49+
smt_pat,
4950
);
5051

5152
#[proc_macro]

hax-lib/macros/src/implementation.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,18 @@ pub fn decreases(attr: pm::TokenStream, item: pm::TokenStream) -> pm::TokenStrea
317317
quote! {#requires #attr #item}.into()
318318
}
319319

320+
/// Allows to add SMT patterns to a lemma.
321+
/// For more informations about SMT patterns, please take a look here: https://fstar-lang.org/tutorial/book/under_the_hood/uth_smt.html#designing-a-library-with-smt-patterns.
322+
#[proc_macro_error]
323+
#[proc_macro_attribute]
324+
pub fn fstar_smt_pat(attr: pm::TokenStream, item: pm::TokenStream) -> pm::TokenStream {
325+
let phi: syn::Expr = parse_macro_input!(attr);
326+
let item: FnLike = parse_macro_input!(item);
327+
let (requires, attr) =
328+
make_fn_decoration(phi, item.sig.clone(), FnDecorationKind::SMTPat, None, None);
329+
quote! {#requires #attr #item}.into()
330+
}
331+
320332
/// Add a logical precondition to a function.
321333
// Note you can use the `forall` and `exists` operators. (TODO: commented out for now, see #297)
322334
/// In the case of a function that has one or more `&mut` inputs, in

hax-lib/macros/src/utils.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub enum FnDecorationKind {
2121
Requires,
2222
Ensures { ret_binder: Pat },
2323
Decreases,
24+
SMTPat,
2425
}
2526

2627
impl ToString for FnDecorationKind {
@@ -29,6 +30,7 @@ impl ToString for FnDecorationKind {
2930
FnDecorationKind::Requires => "requires".to_string(),
3031
FnDecorationKind::Ensures { .. } => "ensures".to_string(),
3132
FnDecorationKind::Decreases { .. } => "decreases".to_string(),
33+
FnDecorationKind::SMTPat { .. } => "SMTPat".to_string(),
3234
}
3335
}
3436
}
@@ -39,6 +41,7 @@ impl From<FnDecorationKind> for AssociationRole {
3941
FnDecorationKind::Requires => AssociationRole::Requires,
4042
FnDecorationKind::Ensures { .. } => AssociationRole::Ensures,
4143
FnDecorationKind::Decreases => AssociationRole::Decreases,
44+
FnDecorationKind::SMTPat => AssociationRole::SMTPat,
4245
}
4346
}
4447
}
@@ -294,16 +297,17 @@ pub fn make_fn_decoration(
294297
if let Some(generics) = generics {
295298
sig.generics = merge_generics(generics, sig.generics);
296299
}
297-
sig.output = if let FnDecorationKind::Decreases = &kind {
298-
syn::parse_quote! { -> () }
299-
} else {
300-
syn::parse_quote! { -> impl Into<::hax_lib::Prop> }
300+
sig.output = match &kind {
301+
FnDecorationKind::Decreases | FnDecorationKind::SMTPat => {
302+
syn::parse_quote! { -> () }
303+
}
304+
_ => syn::parse_quote! { -> impl Into<::hax_lib::Prop> },
301305
};
302306
sig
303307
};
304308
let uid_attr = AttrPayload::Uid(uid.clone());
305309
let late_skip = &AttrPayload::ItemStatus(ItemStatus::Included { late_skip: true });
306-
if let FnDecorationKind::Decreases = &kind {
310+
if let FnDecorationKind::Decreases | FnDecorationKind::SMTPat = &kind {
307311
phi = parse_quote! {::hax_lib::any_to_unit(#phi)};
308312
};
309313
let quantifiers = if let FnDecorationKind::Decreases = &kind {

hax-lib/macros/types/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub enum AssociationRole {
5454
Requires,
5555
Ensures,
5656
Decreases,
57+
SMTPat,
5758
Refine,
5859
/// A quoted piece of backend code to place after or before the
5960
/// extraction of the marked item

tests/attributes/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ mod ensures_on_arity_zero_fns {
3838
#[hax::lemma]
3939
fn add3_lemma(x: u32) -> Proof<{ x <= 10 || x >= u32_max / 3 || add3(x, x, x) == x * 3 }> {}
4040

41+
fn dummy_function(x: u32) -> u32 {
42+
x
43+
}
44+
45+
#[hax::lemma]
46+
#[hax::fstar::smt_pat(x)]
47+
fn apply_dummy_function_lemma(x: u32) -> Proof<{ x == dummy_function(x) }> {}
48+
4149
#[hax::exclude]
4250
pub fn f<'a, T>(c: bool, x: &'a mut T, y: &'a mut T) -> &'a mut T {
4351
if c {

0 commit comments

Comments
 (0)