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)]
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 {
@ -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)]
pub enum AssignmentKind {
Let,

View File

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

View File

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

View File

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

View File

@ -311,22 +311,6 @@ fn test_block_logical_expr() {
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]
fn test_nested_function_calls() {
let src = indoc! {r#"
@ -503,3 +487,20 @@ fn test_newline_module_comments() {
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 {
location: Span::new((), 25..39),
bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::ArrayOfBytes,
}),
tipo: (),
})],
@ -1813,6 +1814,7 @@ fn base16_bytearray_literals() {
value: Box::new(Constant::ByteArray {
location: Span::new((), 25..34),
bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::HexadecimalString,
}),
tipo: (),
}),
@ -1828,6 +1830,7 @@ fn base16_bytearray_literals() {
right: Box::new(expr::UntypedExpr::ByteArray {
location: Span::new((), 71..80),
bytes: vec![0, 170, 255],
preferred_format: ast::ByteArrayFormatPreference::HexadecimalString,
}),
},
doc: None,

View File

@ -350,9 +350,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
..
} => self.infer_tuple_index(*tuple, index, location),
UntypedExpr::ByteArray { location, bytes } => {
Ok(self.infer_byte_array(bytes, location))
}
UntypedExpr::ByteArray {
location, bytes, ..
} => Ok(self.infer_byte_array(bytes, location)),
UntypedExpr::RecordUpdate {
location,
@ -1353,7 +1353,15 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
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.