Skip to content

Commit

Permalink
Merge pull request dtolnay#683 from dtolnay/lit
Browse files Browse the repository at this point in the history
Switch to base10_digits() as the main numeric literal accessor
  • Loading branch information
dtolnay authored Jul 29, 2019
2 parents 10b2679 + 576de4a commit ce05e49
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 230 deletions.
10 changes: 8 additions & 2 deletions codegen/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,14 @@ fn expand_impl_body(defs: &Definitions, node: &Node, name: &str) -> TokenStream
}
}
Data::Private => {
quote! {
write!(formatter, "{:?}", _val.value())
if node.ident == "LitInt" || node.ident == "LitFloat" {
quote! {
write!(formatter, "{}", _val)
}
} else {
quote! {
write!(formatter, "{:?}", _val.value())
}
}
}
}
Expand Down
69 changes: 69 additions & 0 deletions src/bigint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::ops::{AddAssign, MulAssign};

// For implementing base10_digits() accessor on LitInt.
pub struct BigInt {
digits: Vec<u8>,
}

impl BigInt {
pub fn new() -> Self {
BigInt {
digits: Vec::new(),
}
}

pub fn to_string(&self) -> String {
let mut repr = String::with_capacity(self.digits.len());

let mut has_nonzero = false;
for digit in self.digits.iter().rev() {
has_nonzero |= *digit != 0;
if has_nonzero {
repr.push((*digit + b'0') as char);
}
}

if repr.is_empty() {
repr.push('0');
}

repr
}

fn reserve_two_digits(&mut self) {
let len = self.digits.len();
let desired = len
+ !self.digits.ends_with(&[0, 0]) as usize
+ !self.digits.ends_with(&[0]) as usize;
self.digits.resize(desired, 0);
}
}

impl AddAssign<u8> for BigInt {
// Assumes increment <16.
fn add_assign(&mut self, mut increment: u8) {
self.reserve_two_digits();

let mut i = 0;
while increment > 0 {
let sum = self.digits[i] + increment;
self.digits[i] = sum % 10;
increment = sum / 10;
i += 1;
}
}
}

impl MulAssign<u8> for BigInt {
// Assumes base <=16.
fn mul_assign(&mut self, base: u8) {
self.reserve_two_digits();

let mut carry = 0;
for digit in &mut self.digits {
let prod = *digit * base + carry;
*digit = prod % 10;
carry = prod / 10;
}
}
}
7 changes: 5 additions & 2 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2968,9 +2968,12 @@ pub mod parsing {
impl Parse for Index {
fn parse(input: ParseStream) -> Result<Self> {
let lit: LitInt = input.parse()?;
if let IntSuffix::None = lit.suffix() {
if lit.suffix().is_empty() {
Ok(Index {
index: lit.value() as u32,
index: lit
.base10_digits()
.parse()
.map_err(|err| Error::new(lit.span(), err))?,
span: lit.span(),
})
} else {
Expand Down
15 changes: 15 additions & 0 deletions src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::lookahead;
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "parsing")]
use crate::token::Token;
use unicode_xid::UnicodeXID;

pub use proc_macro2::Ident;

Expand Down Expand Up @@ -84,3 +85,17 @@ impl From<Token![_]> for Ident {
Ident::new("_", token.span)
}
}

pub fn xid_ok(symbol: &str) -> bool {
let mut chars = symbol.chars();
let first = chars.next().unwrap();
if !(UnicodeXID::is_xid_start(first) || first == '_') {
return false;
}
for ch in chars {
if !UnicodeXID::is_xid_continue(ch) {
return false;
}
}
true
}
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ pub use crate::attr::{
AttrStyle, Attribute, AttributeArgs, Meta, MetaList, MetaNameValue, NestedMeta,
};

#[cfg(any(feature = "full", feature = "derive"))]
mod bigint;

#[cfg(any(feature = "full", feature = "derive"))]
mod data;
#[cfg(any(feature = "full", feature = "derive"))]
Expand Down Expand Up @@ -372,8 +375,7 @@ pub use crate::lifetime::Lifetime;
mod lit;
#[cfg(any(feature = "full", feature = "derive"))]
pub use crate::lit::{
FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
StrStyle,
Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr, StrStyle,
};

#[cfg(any(feature = "full", feature = "derive"))]
Expand Down
17 changes: 1 addition & 16 deletions src/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::{Ident, Span};
use unicode_xid::UnicodeXID;

#[cfg(feature = "parsing")]
use crate::lookahead;
Expand Down Expand Up @@ -55,21 +54,7 @@ impl Lifetime {
panic!("lifetime name must not be empty");
}

fn xid_ok(symbol: &str) -> bool {
let mut chars = symbol.chars();
let first = chars.next().unwrap();
if !(UnicodeXID::is_xid_start(first) || first == '_') {
return false;
}
for ch in chars {
if !UnicodeXID::is_xid_continue(ch) {
return false;
}
}
true
}

if !xid_ok(&symbol[1..]) {
if !crate::ident::xid_ok(&symbol[1..]) {
panic!("{:?} is not a valid lifetime name", symbol);
}

Expand Down
Loading

0 comments on commit ce05e49

Please sign in to comment.