diff --git a/src/to_tokens.rs b/src/to_tokens.rs index 277d0a5..d34b213 100644 --- a/src/to_tokens.rs +++ b/src/to_tokens.rs @@ -3,6 +3,7 @@ use super::Tokens; use std::borrow::Cow; use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream}; +use proc_macro2::{Spacing, Delimiter}; fn tt(kind: TokenNode) -> TokenTree { TokenTree { @@ -126,8 +127,54 @@ macro_rules! primitive { } primitive! { - i8 i16 i32 i64 isize u8 u16 u32 u64 usize +} + +macro_rules! signed_primitive { + ($($t:ident)*) => ($( + impl ToTokens for $t { + fn to_tokens(&self, tokens: &mut Tokens) { + let val = if *self == <$t>::min_value() { + let mut sub_tokens = Tokens::new(); + (*self as u64).to_tokens(&mut sub_tokens); + sub_tokens.append(tt(TokenNode::Term(Term::intern("as")))); + sub_tokens.append(tt(TokenNode::Term(Term::intern(stringify!($t))))); + let sub_tokens = sub_tokens.into(); + tokens.append(tt(TokenNode::Group(Delimiter::Parenthesis, sub_tokens))); + return + } else if *self < 0 { + tokens.append(tt(TokenNode::Op('-', Spacing::Alone))); + self.abs() + } else { + *self + }; + tokens.append(tt(TokenNode::Literal(Literal::$t(val)))); + } + } + )*) +} + +signed_primitive! { + i8 i16 i32 i64 isize +} + +macro_rules! float_primitive { + ($($t:ident)*) => ($( + impl ToTokens for $t { + fn to_tokens(&self, tokens: &mut Tokens) { + let val = if *self < 0.0 { + tokens.append(tt(TokenNode::Op('-', Spacing::Alone))); + -*self + } else { + *self + }; + tokens.append(tt(TokenNode::Literal(Literal::$t(val)))); + } + } + )*) +} + +float_primitive! { f32 f64 } diff --git a/tests/test.rs b/tests/test.rs index 2a48f1f..04f357b 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -133,7 +133,7 @@ fn test_integer() { #ii8 #ii16 #ii32 #ii64 #iisize #uu8 #uu16 #uu32 #uu64 #uusize }; - let expected = "-1i8 -1i16 -1i32 -1i64 -1isize 1u8 1u16 1u32 1u64 1usize"; + let expected = "- 1i8 - 1i16 - 1i32 - 1i64 - 1isize 1u8 1u16 1u32 1u64 1usize"; assert_eq!(expected, tokens.to_string()); } @@ -290,3 +290,17 @@ fn test_append_tokens() { a.append_all(b); assert_eq!("a b", a.to_string()); } + +#[test] +fn negative_integers() { + let a = -1i32; + let a = quote!(#a); + assert_eq!("- 1i32", a.to_string()); +} + +#[test] +fn negative_min() { + let a = -128i8; + let a = quote!(#a); + assert_eq!("( 18446744073709551488u64 as i8 )", a.to_string()); +}