Allow pattern-matching on bytearrays
- Doesn't allow pattern-matching on G1/G2 elements and strings,
because the use cases for those is unclear and it adds complexity to
the feature.
- We still _parse_ patterns on G1/G2 elements and strings, but emit an
error in those cases.
- The syntax is the same as for bytearray literals (i.e. supports hex,
utf-8 strings or plain arrays of bytes).
This commit is contained in:
63
crates/aiken-lang/src/parser/pattern/bytearray.rs
Normal file
63
crates/aiken-lang/src/parser/pattern/bytearray.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use crate::{
|
||||
ast::UntypedPattern,
|
||||
parser::{error::ParseError, literal, token::Token},
|
||||
};
|
||||
use chumsky::prelude::*;
|
||||
|
||||
pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
||||
literal::bytearray(|value, preferred_format, curve, location, emit| {
|
||||
if curve.is_some() {
|
||||
emit(ParseError::match_on_curve(location));
|
||||
}
|
||||
|
||||
UntypedPattern::ByteArray {
|
||||
location,
|
||||
value,
|
||||
preferred_format,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assert_expr;
|
||||
|
||||
#[test]
|
||||
fn pattern_bytearray() {
|
||||
assert_expr!(
|
||||
r#"
|
||||
when foo is {
|
||||
#"00abcd" -> True
|
||||
"Aiken, rocks!" -> True
|
||||
#[1, 2, 3, 4] -> True
|
||||
#[0x00, 0xab, 0xcd] -> True
|
||||
_ -> False
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_bytearray_g1_element() {
|
||||
assert_expr!(
|
||||
r#"
|
||||
when foo is {
|
||||
#<Bls12_381, G1>"950dfd33da2682260c76038dfb8bad6e84ae9d599a3c151815945ac1e6ef6b1027cd917f3907479d20d636ce437a41f5" -> False
|
||||
_ -> True
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_bytearray_g2_element() {
|
||||
assert_expr!(
|
||||
r#"
|
||||
when foo is {
|
||||
#<Bls12_381, G2>"b0629fa1158c2d23a10413fe91d381a84d25e31d041cd0377d25828498fd02011b35893938ced97535395e4815201e67108bcd4665e0db25d602d76fa791fab706c54abf5e1a9e44b4ac1e6badf3d2ac0328f5e30be341677c8bac5dda7682f1" -> False
|
||||
_ -> True
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
use chumsky::prelude::*;
|
||||
|
||||
mod bytearray;
|
||||
mod constructor;
|
||||
mod discard;
|
||||
mod int;
|
||||
mod list;
|
||||
mod pair;
|
||||
mod string;
|
||||
mod tuple;
|
||||
mod var;
|
||||
|
||||
@@ -12,11 +14,13 @@ use crate::{
|
||||
ast::UntypedPattern,
|
||||
parser::{error::ParseError, token::Token},
|
||||
};
|
||||
pub use bytearray::parser as bytearray;
|
||||
pub use constructor::parser as constructor;
|
||||
pub use discard::parser as discard;
|
||||
pub use int::parser as int;
|
||||
pub use list::parser as list;
|
||||
pub use pair::parser as pair;
|
||||
pub use string::parser as string;
|
||||
pub use tuple::parser as tuple;
|
||||
pub use var::parser as var;
|
||||
|
||||
@@ -28,8 +32,10 @@ pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
||||
constructor(pattern.clone()),
|
||||
discard(),
|
||||
int(),
|
||||
bytearray(),
|
||||
tuple(pattern.clone()),
|
||||
list(pattern),
|
||||
string(),
|
||||
))
|
||||
.then(
|
||||
just(Token::As)
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/bytearray.rs
|
||||
description: "Code:\n\nwhen foo is {\n #\"00abcd\" -> True\n \"Aiken, rocks!\" -> True\n #[1, 2, 3, 4] -> True\n #[0x00, 0xab, 0xcd] -> True\n _ -> False\n}\n"
|
||||
---
|
||||
When {
|
||||
location: 0..138,
|
||||
subject: Var {
|
||||
location: 5..8,
|
||||
name: "foo",
|
||||
},
|
||||
clauses: [
|
||||
UntypedClause {
|
||||
location: 18..35,
|
||||
patterns: [
|
||||
ByteArray {
|
||||
location: 18..27,
|
||||
value: [
|
||||
0,
|
||||
171,
|
||||
205,
|
||||
],
|
||||
preferred_format: HexadecimalString,
|
||||
},
|
||||
],
|
||||
then: Var {
|
||||
location: 31..35,
|
||||
name: "True",
|
||||
},
|
||||
},
|
||||
UntypedClause {
|
||||
location: 40..63,
|
||||
patterns: [
|
||||
ByteArray {
|
||||
location: 40..55,
|
||||
value: [
|
||||
65,
|
||||
105,
|
||||
107,
|
||||
101,
|
||||
110,
|
||||
44,
|
||||
32,
|
||||
114,
|
||||
111,
|
||||
99,
|
||||
107,
|
||||
115,
|
||||
33,
|
||||
],
|
||||
preferred_format: Utf8String,
|
||||
},
|
||||
],
|
||||
then: Var {
|
||||
location: 59..63,
|
||||
name: "True",
|
||||
},
|
||||
},
|
||||
UntypedClause {
|
||||
location: 68..89,
|
||||
patterns: [
|
||||
ByteArray {
|
||||
location: 68..81,
|
||||
value: [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
],
|
||||
preferred_format: ArrayOfBytes(
|
||||
Decimal {
|
||||
numeric_underscore: false,
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
then: Var {
|
||||
location: 85..89,
|
||||
name: "True",
|
||||
},
|
||||
},
|
||||
UntypedClause {
|
||||
location: 94..121,
|
||||
patterns: [
|
||||
ByteArray {
|
||||
location: 94..113,
|
||||
value: [
|
||||
0,
|
||||
171,
|
||||
205,
|
||||
],
|
||||
preferred_format: ArrayOfBytes(
|
||||
Hexadecimal,
|
||||
),
|
||||
},
|
||||
],
|
||||
then: Var {
|
||||
location: 117..121,
|
||||
name: "True",
|
||||
},
|
||||
},
|
||||
UntypedClause {
|
||||
location: 126..136,
|
||||
patterns: [
|
||||
Discard {
|
||||
name: "_",
|
||||
location: 126..127,
|
||||
},
|
||||
],
|
||||
then: Var {
|
||||
location: 131..136,
|
||||
name: "False",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/bytearray.rs
|
||||
description: "Invalid code (parse error):\n\nwhen foo is {\n #<Bls12_381, G1>\"950dfd33da2682260c76038dfb8bad6e84ae9d599a3c151815945ac1e6ef6b1027cd917f3907479d20d636ce437a41f5\" -> False\n _ -> True\n}\n"
|
||||
---
|
||||
[
|
||||
ParseError {
|
||||
kind: PatternMatchOnCurvePoint,
|
||||
span: 18..132,
|
||||
while_parsing: None,
|
||||
expected: {},
|
||||
label: Some(
|
||||
"cannot pattern-match on curve point",
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/bytearray.rs
|
||||
description: "Invalid code (parse error):\n\nwhen foo is {\n #<Bls12_381, G2>\"b0629fa1158c2d23a10413fe91d381a84d25e31d041cd0377d25828498fd02011b35893938ced97535395e4815201e67108bcd4665e0db25d602d76fa791fab706c54abf5e1a9e44b4ac1e6badf3d2ac0328f5e30be341677c8bac5dda7682f1\" -> False\n _ -> True\n}\n"
|
||||
---
|
||||
[
|
||||
ParseError {
|
||||
kind: PatternMatchOnCurvePoint,
|
||||
span: 18..228,
|
||||
while_parsing: None,
|
||||
expected: {},
|
||||
label: Some(
|
||||
"cannot pattern-match on curve point",
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
source: crates/aiken-lang/src/parser/pattern/string.rs
|
||||
description: "Invalid code (parse error):\n\nwhen foo is {\n @\"foo\" -> True\n}\n"
|
||||
---
|
||||
[
|
||||
ParseError {
|
||||
kind: PatternMatchOnString,
|
||||
span: 16..22,
|
||||
while_parsing: None,
|
||||
expected: {},
|
||||
label: Some(
|
||||
"cannot pattern-match on string",
|
||||
),
|
||||
},
|
||||
]
|
||||
33
crates/aiken-lang/src/parser/pattern/string.rs
Normal file
33
crates/aiken-lang/src/parser/pattern/string.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use crate::{
|
||||
ast::{ByteArrayFormatPreference, UntypedPattern},
|
||||
parser::{error::ParseError, literal, token::Token},
|
||||
};
|
||||
use chumsky::prelude::*;
|
||||
|
||||
pub fn parser() -> impl Parser<Token, UntypedPattern, Error = ParseError> {
|
||||
literal::string().validate(|_, location, emit| {
|
||||
emit(ParseError::match_string(location));
|
||||
|
||||
UntypedPattern::ByteArray {
|
||||
location,
|
||||
value: Vec::new(),
|
||||
preferred_format: ByteArrayFormatPreference::Utf8String,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::assert_expr;
|
||||
|
||||
#[test]
|
||||
fn pattern_string() {
|
||||
assert_expr!(
|
||||
r#"
|
||||
when foo is {
|
||||
@"foo" -> True
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user