Support declaring bytearray literals as base16 strings.
This commit is contained in:
parent
6f8d1698fe
commit
3139c85fe8
|
@ -75,6 +75,7 @@ name = "aiken-lang"
|
||||||
version = "0.0.26"
|
version = "0.0.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chumsky",
|
"chumsky",
|
||||||
|
"hex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"indoc",
|
"indoc",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
|
|
@ -12,6 +12,7 @@ authors = ["Lucas Rosa <x@rvcas.dev>", "Kasey White <kwhitemsg@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chumsky = "0.8.0"
|
chumsky = "0.8.0"
|
||||||
|
hex = "0.4.3"
|
||||||
indexmap = "1.9.1"
|
indexmap = "1.9.1"
|
||||||
indoc = "1.0.7"
|
indoc = "1.0.7"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
|
|
|
@ -344,7 +344,7 @@ fn constant_value_parser() -> impl Parser<Token, ast::UntypedConstant, Error = P
|
||||||
elements,
|
elements,
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_bytearray_parser = just(Token::Hash)
|
let constant_bytearray_list_parser = just(Token::Hash)
|
||||||
.ignore_then(
|
.ignore_then(
|
||||||
select! {Token::Int {value} => value}
|
select! {Token::Int {value} => value}
|
||||||
.validate(|value, span, emit| {
|
.validate(|value, span, emit| {
|
||||||
|
@ -372,6 +372,27 @@ fn constant_value_parser() -> impl Parser<Token, ast::UntypedConstant, Error = P
|
||||||
bytes,
|
bytes,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let constant_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_with_span(|bytes, span| ast::UntypedConstant::ByteArray {
|
||||||
|
location: span,
|
||||||
|
bytes,
|
||||||
|
});
|
||||||
|
|
||||||
|
let constant_bytearray_parser = choice((
|
||||||
|
constant_bytearray_list_parser,
|
||||||
|
constant_bytearray_hexstring_parser,
|
||||||
|
));
|
||||||
|
|
||||||
let constant_list_parser = r
|
let constant_list_parser = r
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(just(Token::Comma))
|
.separated_by(just(Token::Comma))
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashSet;
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
|
|
||||||
use crate::{ast::Span, parser::token::Token};
|
use crate::{ast::Span, parser::token::Token};
|
||||||
|
use indoc::formatdoc;
|
||||||
|
|
||||||
#[derive(Debug, Diagnostic, thiserror::Error)]
|
#[derive(Debug, Diagnostic, thiserror::Error)]
|
||||||
#[error("{kind}\n")]
|
#[error("{kind}\n")]
|
||||||
|
@ -35,6 +36,16 @@ impl ParseError {
|
||||||
label: None,
|
label: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn malformed_base16_string_literal(span: Span) -> Self {
|
||||||
|
Self {
|
||||||
|
kind: ErrorKind::MalformedBase16StringLiteral,
|
||||||
|
span,
|
||||||
|
while_parsing: None,
|
||||||
|
expected: HashSet::new(),
|
||||||
|
label: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for ParseError {
|
impl PartialEq for ParseError {
|
||||||
|
@ -91,6 +102,18 @@ pub enum ErrorKind {
|
||||||
#[help]
|
#[help]
|
||||||
hint: Option<String>,
|
hint: Option<String>,
|
||||||
},
|
},
|
||||||
|
#[error("I tripped over a malformed base16-encoded string literal")]
|
||||||
|
#[diagnostic(help("{}", formatdoc! {
|
||||||
|
r#"You can declare literal bytearrays from base16-encoded (a.k.a. hexadecimal)
|
||||||
|
string literals.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
pub const my_policy_id =
|
||||||
|
#"f4c9f9c4252d86702c2f4c2e49e6648c7cffe3c8f2b6b7d779788f50"
|
||||||
|
"#
|
||||||
|
}))]
|
||||||
|
MalformedBase16StringLiteral,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use indoc::indoc;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, DataType, Function, Span, TypeAlias, Use},
|
ast::{self, Constant, DataType, Function, ModuleConstant, Span, TypeAlias, Use},
|
||||||
expr, parser,
|
expr, parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1542,3 +1542,49 @@ fn parse_tuple() {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn plain_bytearray_literals() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
pub const my_policy_id = #[0, 170, 255]
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definition(
|
||||||
|
code,
|
||||||
|
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 0..39),
|
||||||
|
public: true,
|
||||||
|
name: "my_policy_id".to_string(),
|
||||||
|
annotation: None,
|
||||||
|
value: Box::new(Constant::ByteArray {
|
||||||
|
location: Span::new((), 25..39),
|
||||||
|
bytes: vec![0, 170, 255],
|
||||||
|
}),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn base16_bytearray_literals() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
pub const my_policy_id = #"00aaff"
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definition(
|
||||||
|
code,
|
||||||
|
ast::UntypedDefinition::ModuleConstant(ModuleConstant {
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 0..34),
|
||||||
|
public: true,
|
||||||
|
name: "my_policy_id".to_string(),
|
||||||
|
annotation: None,
|
||||||
|
value: Box::new(Constant::ByteArray {
|
||||||
|
location: Span::new((), 25..34),
|
||||||
|
bytes: vec![0, 170, 255],
|
||||||
|
}),
|
||||||
|
tipo: (),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue