Preserve numeric underscore and hexadecimal notation through formatting.

This commit is contained in:
KtorZ 2023-06-08 16:37:20 +02:00
parent 0b7682306f
commit 6bd8e94e17
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
4 changed files with 92 additions and 22 deletions

View File

@ -1,8 +1,3 @@
use itertools::Itertools;
use ordinal::Ordinal;
use std::sync::Arc;
use vec1::Vec1;
use crate::{ use crate::{
ast::{ ast::{
Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg, Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
@ -23,6 +18,11 @@ use crate::{
}, },
tipo::{self, Type}, tipo::{self, Type},
}; };
use itertools::Itertools;
use num_bigint::BigInt;
use ordinal::Ordinal;
use std::sync::Arc;
use vec1::Vec1;
const INDENT: isize = 2; const INDENT: isize = 2;
const DOCS_MAX_COLUMNS: isize = 80; const DOCS_MAX_COLUMNS: isize = 80;
@ -665,7 +665,7 @@ impl<'comments> Formatter<'comments> {
.append("\"") .append("\"")
.append(Document::String(hex::encode(bytes))) .append(Document::String(hex::encode(bytes)))
.append("\""), .append("\""),
ByteArrayFormatPreference::ArrayOfBytes(base) => "#" ByteArrayFormatPreference::ArrayOfBytes(Base::Decimal { .. }) => "#"
.to_doc() .to_doc()
.append( .append(
flex_break("[", "[") flex_break("[", "[")
@ -675,6 +675,25 @@ impl<'comments> Formatter<'comments> {
.append("]"), .append("]"),
) )
.group(), .group(),
ByteArrayFormatPreference::ArrayOfBytes(Base::Hexadecimal) => "#"
.to_doc()
.append(
flex_break("[", "[")
.append(join(
bytes.iter().map(|b| {
Document::String(if *b < 16 {
format!("0x0{b:x}")
} else {
format!("{b:#x}")
})
}),
break_(",", ", "),
))
.nest(INDENT)
.append(break_(",", ""))
.append("]"),
)
.group(),
ByteArrayFormatPreference::Utf8String => nil() ByteArrayFormatPreference::Utf8String => nil()
.append("\"") .append("\"")
.append(Document::String(String::from_utf8(bytes.to_vec()).unwrap())) .append(Document::String(String::from_utf8(bytes.to_vec()).unwrap()))
@ -682,8 +701,37 @@ impl<'comments> Formatter<'comments> {
} }
} }
pub fn int<'a>(&mut self, i: &'a str, base: &Base) -> Document<'a> { pub fn int<'a>(&mut self, s: &'a str, base: &Base) -> Document<'a> {
i.to_doc() match base {
Base::Decimal { numeric_underscore } if *numeric_underscore => {
let s = s
.chars()
.rev()
.enumerate()
.flat_map(|(i, c)| {
if i != 0 && i % 3 == 0 {
Some('_')
} else {
None
}
.into_iter()
.chain(std::iter::once(c))
})
.collect::<String>()
.chars()
.rev()
.collect::<String>();
Document::String(s)
}
Base::Decimal { .. } => s.to_doc(),
Base::Hexadecimal => Document::String(format!(
"0x{}",
BigInt::parse_bytes(s.as_bytes(), 10)
.expect("Invalid parsed hexadecimal digits ?!")
.to_str_radix(16),
)),
}
} }
pub fn expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> { pub fn expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {

View File

@ -20,7 +20,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
.at_least(1) .at_least(1)
.at_most(3) .at_most(3)
.separated_by(just("_")) .separated_by(just("_"))
.at_least(1) .at_least(2)
.flatten() .flatten()
.collect::<String>() .collect::<String>()
.map(|value| Token::Int { .map(|value| Token::Int {

View File

@ -838,9 +838,10 @@ fn pipes_and_expressions() {
fn hex_and_numeric_underscore() { fn hex_and_numeric_underscore() {
let src = indoc! {r#" let src = indoc! {r#"
fn foo() { fn foo() {
let a = 1_000_000 let a = 1_000_000 + 1_423 + 10393841
let b = 0xA4 let b = 0xa4 - 0xcd
let c = #[ 0xFD, 0x12, 0x00, 0x1B ] let c = #[0xfd, 0x12, 0x00, 0x1b, 0x0a, 0x90]
let d = -100_000
} }
"#}; "#};

View File

@ -3592,6 +3592,7 @@ fn int_parsing_numeric_underscore() {
fn foo() { fn foo() {
let i = 1_234_567 let i = 1_234_567
let j = 1_000_000 let j = 1_000_000
let k = -10_000
} }
"#}; "#};
assert_definitions( assert_definitions(
@ -3599,49 +3600,69 @@ fn int_parsing_numeric_underscore() {
vec![ast::Definition::Fn(Function { vec![ast::Definition::Fn(Function {
arguments: vec![], arguments: vec![],
body: expr::UntypedExpr::Sequence { body: expr::UntypedExpr::Sequence {
location: Span::new((), 13..50), location: Span::new((), 17..76),
expressions: vec![ expressions: vec![
expr::UntypedExpr::Assignment { expr::UntypedExpr::Assignment {
location: Span::new((), 13..30), location: Span::new((), 17..34),
value: Box::new(expr::UntypedExpr::Int { value: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 21..30), location: Span::new((), 25..34),
value: "1234567".to_string(), value: "1234567".to_string(),
base: Base::Decimal { base: Base::Decimal {
numeric_underscore: true, numeric_underscore: true,
}, },
}), }),
pattern: ast::Pattern::Var { pattern: ast::Pattern::Var {
location: Span::new((), 17..18), location: Span::new((), 21..22),
name: "i".to_string(), name: "i".to_string(),
}, },
kind: ast::AssignmentKind::Let, kind: ast::AssignmentKind::Let,
annotation: None, annotation: None,
}, },
expr::UntypedExpr::Assignment { expr::UntypedExpr::Assignment {
location: Span::new((), 33..50), location: Span::new((), 39..56),
value: Box::new(expr::UntypedExpr::Int { value: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 41..50), location: Span::new((), 47..56),
value: "1000000".to_string(), value: "1000000".to_string(),
base: Base::Decimal { base: Base::Decimal {
numeric_underscore: true, numeric_underscore: true,
}, },
}), }),
pattern: ast::Pattern::Var { pattern: ast::Pattern::Var {
location: Span::new((), 37..38), location: Span::new((), 43..44),
name: "j".to_string(), name: "j".to_string(),
}, },
kind: ast::AssignmentKind::Let, kind: ast::AssignmentKind::Let,
annotation: None, annotation: None,
}, },
expr::UntypedExpr::Assignment {
location: Span::new((), 61..76),
value: Box::new(expr::UntypedExpr::UnOp {
op: ast::UnOp::Negate,
location: Span::new((), 69..76),
value: Box::new(expr::UntypedExpr::Int {
location: Span::new((), 70..76),
value: "10000".to_string(),
base: Base::Decimal {
numeric_underscore: true,
},
}),
}),
pattern: ast::Pattern::Var {
location: Span::new((), 65..66),
name: "k".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
], ],
}, },
doc: None, doc: None,
location: Span::new((), 0..8), location: Span::new((), 2..10),
name: "foo".to_string(), name: "foo".to_string(),
public: false, public: false,
return_annotation: None, return_annotation: None,
return_type: (), return_type: (),
end_position: 51, end_position: 77,
can_error: true, can_error: true,
})], })],
) )