Preserve bytearray format choice from input.

This commit is contained in:
KtorZ 2023-02-17 18:44:47 +01:00
parent f3cdc05875
commit 98b89f32e1
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
7 changed files with 148 additions and 78 deletions

View File

@ -326,11 +326,21 @@ pub struct DefinitionLocation<'module> {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Constant { pub enum Constant {
Int { location: Span, value: String }, Int {
location: Span,
value: String,
},
String { location: Span, value: String }, String {
location: Span,
value: String,
},
ByteArray { location: Span, bytes: Vec<u8> }, ByteArray {
location: Span,
bytes: Vec<u8>,
preferred_format: ByteArrayFormatPreference,
},
} }
impl Constant { impl Constant {
@ -748,6 +758,13 @@ impl<A, B> Pattern<A, B> {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum ByteArrayFormatPreference {
HexadecimalString,
ArrayOfBytes,
Utf8String,
}
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum AssignmentKind { pub enum AssignmentKind {
Let, Let,

View File

@ -4,9 +4,9 @@ use vec1::Vec1;
use crate::{ use crate::{
ast::{ ast::{
Annotation, Arg, AssignmentKind, BinOp, CallArg, Clause, DefinitionLocation, IfBranch, Annotation, Arg, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg, Clause,
Pattern, RecordUpdateSpread, Span, TraceKind, TypedRecordUpdateArg, UnOp, DefinitionLocation, IfBranch, Pattern, RecordUpdateSpread, Span, TraceKind,
UntypedRecordUpdateArg, TypedRecordUpdateArg, UnOp, UntypedRecordUpdateArg,
}, },
builtins::void, builtins::void,
tipo::{ModuleValueConstructor, PatternConstructor, Type, ValueConstructor}, tipo::{ModuleValueConstructor, PatternConstructor, Type, ValueConstructor},
@ -361,6 +361,7 @@ pub enum UntypedExpr {
ByteArray { ByteArray {
location: Span, location: Span,
bytes: Vec<u8>, bytes: Vec<u8>,
preferred_format: ByteArrayFormatPreference,
}, },
PipeLine { PipeLine {

View File

@ -5,12 +5,12 @@ use vec1::Vec1;
use crate::{ use crate::{
ast::{ ast::{
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, ClauseGuard, Constant, DataType, Annotation, Arg, ArgName, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg,
Definition, Function, IfBranch, ModuleConstant, Pattern, RecordConstructor, ClauseGuard, Constant, DataType, Definition, Function, IfBranch, ModuleConstant, Pattern,
RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, UnOp, RecordConstructor, RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias,
UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedDefinition, TypedArg, UnOp, UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard,
UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, Validator, UntypedDefinition, UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg,
CAPTURE_VARIABLE, Use, Validator, CAPTURE_VARIABLE,
}, },
docvec, docvec,
expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR}, expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
@ -326,7 +326,11 @@ impl<'comments> Formatter<'comments> {
fn const_expr<'a>(&mut self, value: &'a Constant) -> Document<'a> { fn const_expr<'a>(&mut self, value: &'a Constant) -> Document<'a> {
match value { match value {
Constant::ByteArray { bytes, .. } => self.bytearray(bytes), Constant::ByteArray {
bytes,
preferred_format,
..
} => self.bytearray(bytes, preferred_format),
Constant::Int { value, .. } => value.to_doc(), Constant::Int { value, .. } => value.to_doc(),
Constant::String { value, .. } => self.string(value), Constant::String { value, .. } => self.string(value),
} }
@ -635,18 +639,40 @@ impl<'comments> Formatter<'comments> {
} }
} }
pub fn bytearray<'a>(&mut self, bytes: &'a [u8]) -> Document<'a> { pub fn bytearray<'a>(
"#".to_doc() &mut self,
bytes: &'a [u8],
preferred_format: &ByteArrayFormatPreference,
) -> Document<'a> {
match preferred_format {
ByteArrayFormatPreference::HexadecimalString => "#"
.to_doc()
.append("\"") .append("\"")
.append(Document::String(hex::encode(bytes))) .append(Document::String(hex::encode(bytes)))
.append("\"") .append("\""),
ByteArrayFormatPreference::ArrayOfBytes => "#"
.to_doc()
.append(
flex_break("[", "[")
.append(join(bytes.iter().map(|b| b.to_doc()), break_(",", ", ")))
.nest(INDENT)
.append(break_(",", ""))
.append("]"),
)
.group(),
ByteArrayFormatPreference::Utf8String => todo!(),
}
} }
pub fn expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> { pub fn expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
let comments = self.pop_comments(expr.start_byte_index()); let comments = self.pop_comments(expr.start_byte_index());
let document = match expr { let document = match expr {
UntypedExpr::ByteArray { bytes, .. } => self.bytearray(bytes), UntypedExpr::ByteArray {
bytes,
preferred_format,
..
} => self.bytearray(bytes, preferred_format),
UntypedExpr::If { UntypedExpr::If {
branches, branches,

View File

@ -7,7 +7,10 @@ pub mod lexer;
pub mod token; pub mod token;
use crate::{ use crate::{
ast::{self, BinOp, Span, TraceKind, UnOp, UntypedDefinition, CAPTURE_VARIABLE}, ast::{
self, BinOp, ByteArrayFormatPreference, Span, TraceKind, UnOp, UntypedDefinition,
CAPTURE_VARIABLE,
},
expr, expr,
}; };
@ -402,9 +405,12 @@ fn constant_value_parser() -> impl Parser<Token, ast::Constant, Error = ParseErr
}); });
let constant_bytearray_parser = let constant_bytearray_parser =
bytearray_parser().map_with_span(|bytes, span| ast::Constant::ByteArray { bytearray_parser().map_with_span(|(preferred_format, bytes), span| {
ast::Constant::ByteArray {
location: span, location: span,
bytes, bytes,
preferred_format,
}
}); });
choice(( choice((
@ -414,8 +420,10 @@ fn constant_value_parser() -> impl Parser<Token, ast::Constant, Error = ParseErr
)) ))
} }
pub fn bytearray_parser() -> impl Parser<Token, Vec<u8>, Error = ParseError> { pub fn bytearray_parser(
let bytearray_list_parser = just(Token::Hash).ignore_then( ) -> impl Parser<Token, (ByteArrayFormatPreference, Vec<u8>), Error = ParseError> {
let bytearray_list_parser = just(Token::Hash)
.ignore_then(
select! {Token::Int {value} => value} select! {Token::Int {value} => value}
.validate(|value, span, emit| { .validate(|value, span, emit| {
let byte: u8 = match value.parse() { let byte: u8 = match value.parse() {
@ -436,10 +444,12 @@ pub fn bytearray_parser() -> impl Parser<Token, Vec<u8>, Error = ParseError> {
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
.delimited_by(just(Token::LeftSquare), just(Token::RightSquare)), .delimited_by(just(Token::LeftSquare), just(Token::RightSquare)),
); )
.map(|token| (ByteArrayFormatPreference::ArrayOfBytes, token));
let bytearray_hexstring_parser = let bytearray_hexstring_parser = just(Token::Hash)
just(Token::Hash).ignore_then(select! {Token::String {value} => value}.validate( .ignore_then(
select! {Token::String {value} => value}.validate(
|value, span, emit| match hex::decode(value) { |value, span, emit| match hex::decode(value) {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(_) => { Err(_) => {
@ -447,7 +457,9 @@ pub fn bytearray_parser() -> impl Parser<Token, Vec<u8>, Error = ParseError> {
vec![] vec![]
} }
}, },
)); ),
)
.map(|token| (ByteArrayFormatPreference::HexadecimalString, token));
choice((bytearray_list_parser, bytearray_hexstring_parser)) choice((bytearray_list_parser, bytearray_hexstring_parser))
} }
@ -816,10 +828,12 @@ pub fn expr_parser(
elems, elems,
}); });
let bytearray = let bytearray = bytearray_parser().map_with_span(|(preferred_format, bytes), span| {
bytearray_parser().map_with_span(|bytes, span| expr::UntypedExpr::ByteArray { expr::UntypedExpr::ByteArray {
location: span, location: span,
bytes, bytes,
preferred_format,
}
}); });
let list_parser = just(Token::LeftSquare) let list_parser = just(Token::LeftSquare)

View File

@ -311,22 +311,6 @@ fn test_block_logical_expr() {
assert_fmt(src, expected); assert_fmt(src, expected);
} }
#[test]
fn test_format_bytearray_literals() {
let src = indoc! {r#"
const foo = #"ff00"
const bar = #[0, 255]
"#};
let expected = indoc! { r#"
const foo = #"ff00"
const bar = #"00ff"
"#};
assert_fmt(src, expected);
}
#[test] #[test]
fn test_nested_function_calls() { fn test_nested_function_calls() {
let src = indoc! {r#" let src = indoc! {r#"
@ -503,3 +487,20 @@ fn test_newline_module_comments() {
assert_fmt(src, out); assert_fmt(src, out);
} }
#[test]
fn test_bytearray_literals() {
let src = indoc! {r#"
const foo_const_array = #[102, 111, 111]
const foo_const_hex = #"666f6f"
fn foo() {
let foo_const_array = #[102, 111, 111]
let foo_const_hex = #"666f6f"
}
"#};
assert_fmt(src, src);
}

View File

@ -1785,6 +1785,7 @@ fn plain_bytearray_literals() {
value: Box::new(Constant::ByteArray { value: Box::new(Constant::ByteArray {
location: Span::new((), 25..39), location: Span::new((), 25..39),
bytes: vec![0, 170, 255], bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::ArrayOfBytes,
}), }),
tipo: (), tipo: (),
})], })],
@ -1813,6 +1814,7 @@ fn base16_bytearray_literals() {
value: Box::new(Constant::ByteArray { value: Box::new(Constant::ByteArray {
location: Span::new((), 25..34), location: Span::new((), 25..34),
bytes: vec![0, 170, 255], bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::HexadecimalString,
}), }),
tipo: (), tipo: (),
}), }),
@ -1828,6 +1830,7 @@ fn base16_bytearray_literals() {
right: Box::new(expr::UntypedExpr::ByteArray { right: Box::new(expr::UntypedExpr::ByteArray {
location: Span::new((), 71..80), location: Span::new((), 71..80),
bytes: vec![0, 170, 255], bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::HexadecimalString,
}), }),
}, },
doc: None, doc: None,

View File

@ -350,9 +350,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
.. ..
} => self.infer_tuple_index(*tuple, index, location), } => self.infer_tuple_index(*tuple, index, location),
UntypedExpr::ByteArray { location, bytes } => { UntypedExpr::ByteArray {
Ok(self.infer_byte_array(bytes, location)) location, bytes, ..
} } => Ok(self.infer_byte_array(bytes, location)),
UntypedExpr::RecordUpdate { UntypedExpr::RecordUpdate {
location, location,
@ -1353,7 +1353,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
location, value, .. location, value, ..
} => Ok(Constant::String { location, value }), } => Ok(Constant::String { location, value }),
Constant::ByteArray { location, bytes } => Ok(Constant::ByteArray { location, bytes }), Constant::ByteArray {
location,
bytes,
preferred_format,
} => Ok(Constant::ByteArray {
location,
bytes,
preferred_format,
}),
}?; }?;
// Check type annotation is accurate. // Check type annotation is accurate.