Skip to content

Commit f9781c4

Browse files
committed
feat(hax-lib): int!: support hex, octal and binary literals
1 parent d1e0d3c commit f9781c4

File tree

4 files changed

+30
-20
lines changed

4 files changed

+30
-20
lines changed

hax-lib/macros/src/implementation.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -809,27 +809,13 @@ pub fn pv_handwritten(_attr: pm::TokenStream, item: pm::TokenStream) -> pm::Toke
809809
#[proc_macro_error]
810810
#[proc_macro]
811811
pub fn int(payload: pm::TokenStream) -> pm::TokenStream {
812-
let mut tokens = payload.into_iter().peekable();
813-
let negative = matches!(tokens.peek(), Some(pm::TokenTree::Punct(p)) if p.as_char() == '-');
814-
if negative {
815-
tokens.next();
812+
let n: LitInt = parse_macro_input!(payload);
813+
let suffix = n.suffix();
814+
if !suffix.is_empty() {
815+
abort_call_site!("The literal suffix `{suffix}` was unexpected.")
816816
}
817-
let [pm::TokenTree::Literal(lit)] = &tokens.collect::<Vec<_>>()[..] else {
818-
abort_call_site!("Expected exactly one numeric literal");
819-
};
820-
let lit = format!("{lit}");
821-
// Allow negative numbers
822-
let mut lit = lit.strip_prefix("-").unwrap_or(lit.as_str()).to_string();
823-
if let Some(faulty) = lit.chars().find(|ch| !ch.is_ascii_digit()) {
824-
abort_call_site!(format!("Expected a digit, found {faulty}"));
825-
}
826-
if negative {
827-
lit = format!("-{lit}");
828-
}
829-
quote! {
830-
::hax_lib::int::Int::_unsafe_from_str(#lit)
831-
}
832-
.into()
817+
let digits = n.base10_digits();
818+
quote! {::hax_lib::int::Int::_unsafe_from_str(#digits)}.into()
833819
}
834820

835821
macro_rules! make_quoting_item_proc_macro {

test-harness/src/snapshots/toolchain__literals into-coq.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ Export hax_lib.
5050

5151
Definition math_integers (x : t_Int) `{andb (f_gt (x) (impl_Int__e_unsafe_from_str (("0"%string : string)))) (f_lt (x) (impl_Int__e_unsafe_from_str (("16"%string : string)))) = true} : t_u8 :=
5252
let _ : t_Int := f_lift ((3 : t_usize)) in
53+
let e_neg_dec := impl_Int__e_unsafe_from_str (("-340282366920938463463374607431768211455000"%string : string)) in
54+
let e_pos_dec := impl_Int__e_unsafe_from_str (("340282366920938463463374607431768211455000"%string : string)) in
55+
let e_neg_hex := impl_Int__e_unsafe_from_str (("-340282366920938463463374607431768211455000"%string : string)) in
56+
let e_pos_hex := impl_Int__e_unsafe_from_str (("340282366920938463463374607431768211455000"%string : string)) in
57+
let e_neg_octal := impl_Int__e_unsafe_from_str (("-340282366920938463463374607431768211455000"%string : string)) in
58+
let e_pos_octal := impl_Int__e_unsafe_from_str (("340282366920938463463374607431768211455000"%string : string)) in
59+
let e_neg_bin := impl_Int__e_unsafe_from_str (("-340282366920938463463374607431768211455000"%string : string)) in
60+
let e_pos_bin := impl_Int__e_unsafe_from_str (("340282366920938463463374607431768211455000"%string : string)) in
5361
let _ := f_gt (impl_Int__e_unsafe_from_str (("-340282366920938463463374607431768211455000"%string : string))) (impl_Int__e_unsafe_from_str (("340282366920938463463374607431768211455000"%string : string))) in
5462
let _ := f_lt (x) (x) in
5563
let _ := f_ge (x) (x) in

test-harness/src/snapshots/toolchain__literals into-fstar.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ let math_integers (x: Hax_lib.Int.t_Int)
3838
(requires x > (0 <: Hax_lib.Int.t_Int) && x < (16 <: Hax_lib.Int.t_Int))
3939
(fun _ -> Prims.l_True) =
4040
let _:Hax_lib.Int.t_Int = Rust_primitives.Hax.Int.from_machine (mk_usize 3) in
41+
let e_neg_dec:Hax_lib.Int.t_Int = (-340282366920938463463374607431768211455000) in
42+
let e_pos_dec:Hax_lib.Int.t_Int = 340282366920938463463374607431768211455000 in
43+
let e_neg_hex:Hax_lib.Int.t_Int = (-340282366920938463463374607431768211455000) in
44+
let e_pos_hex:Hax_lib.Int.t_Int = 340282366920938463463374607431768211455000 in
45+
let e_neg_octal:Hax_lib.Int.t_Int = (-340282366920938463463374607431768211455000) in
46+
let e_pos_octal:Hax_lib.Int.t_Int = 340282366920938463463374607431768211455000 in
47+
let e_neg_bin:Hax_lib.Int.t_Int = (-340282366920938463463374607431768211455000) in
48+
let e_pos_bin:Hax_lib.Int.t_Int = 340282366920938463463374607431768211455000 in
4149
let _:bool =
4250
((-340282366920938463463374607431768211455000) <: Hax_lib.Int.t_Int) >
4351
(340282366920938463463374607431768211455000 <: Hax_lib.Int.t_Int)

tests/literals/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ use hax_lib::*;
44
#[hax_lib::requires(x > int!(0) && x < int!(16))]
55
fn math_integers(x: Int) -> u8 {
66
let _: Int = 3usize.lift();
7+
let _neg_dec = int!(-340282366920938463463374607431768211455000);
8+
let _pos_dec = int!(340282366920938463463374607431768211455000);
9+
let _neg_hex = int!(-0x3E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC18);
10+
let _pos_hex = int!(0x3E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC18);
11+
let _neg_octal = int!(-0o7637777777777777777777777777777777777777776030);
12+
let _pos_octal = int!(0o7637777777777777777777777777777777777777776030);
13+
let _neg_bin = int!(-0b111110011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000011000);
14+
let _pos_bin = int!(0b111110011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000011000);
715
let _ = int!(-340282366920938463463374607431768211455000)
816
> int!(340282366920938463463374607431768211455000);
917
let _ = x < x;

0 commit comments

Comments
 (0)