More tuple pattern work
This commit is contained in:
parent
48e2d9a683
commit
a03f570266
1
TODO.md
1
TODO.md
@ -3,6 +3,7 @@
|
|||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
* Get a test library for running many unit tests working
|
* Get a test library for running many unit tests working
|
||||||
|
* Write a human-readable display of the AST
|
||||||
|
|
||||||
## Symbols
|
## Symbols
|
||||||
|
|
||||||
|
@ -830,6 +830,55 @@ fn if_expr() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn advanced_if_expr() {
|
||||||
|
|
||||||
|
parse_test_wrap_ast! {
|
||||||
|
r#"
|
||||||
|
if (45, "panda", false, 2.2) {
|
||||||
|
is (49, "pablo", _, 28.4) then "no"
|
||||||
|
is (_, "panda", _, -2.2) then "yes"
|
||||||
|
is _ then "maybe"
|
||||||
|
}"#,
|
||||||
|
exst!(
|
||||||
|
IfExpression {
|
||||||
|
discriminator: Some(bx!(ex!(s r#"(45, "panda", false, 2.2)"#))),
|
||||||
|
body: bx!(IfExpressionBody::CondList(vec![
|
||||||
|
ConditionArm {
|
||||||
|
condition: Condition::Pattern(Pattern::TuplePattern(
|
||||||
|
vec![
|
||||||
|
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(49) }),
|
||||||
|
Pattern::Literal(PatternLiteral::StringPattern(rc!(pablo))),
|
||||||
|
Pattern::Ignored,
|
||||||
|
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: FloatLiteral(28.4) }),
|
||||||
|
]
|
||||||
|
)),
|
||||||
|
guard: None,
|
||||||
|
body: vec![exst!(s r#""no""#)],
|
||||||
|
},
|
||||||
|
ConditionArm {
|
||||||
|
condition: Condition::Pattern(Pattern::TuplePattern(
|
||||||
|
vec![
|
||||||
|
Pattern::Ignored,
|
||||||
|
Pattern::Literal(PatternLiteral::StringPattern(rc!(panda))),
|
||||||
|
Pattern::Ignored,
|
||||||
|
Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: FloatLiteral(2.2) }),
|
||||||
|
]
|
||||||
|
)),
|
||||||
|
guard: None,
|
||||||
|
body: vec![exst!(s r#""yes""#)],
|
||||||
|
},
|
||||||
|
ConditionArm {
|
||||||
|
condition: Condition::Pattern(Pattern::Ignored),
|
||||||
|
guard: None,
|
||||||
|
body: vec![exst!(s r#""maybe""#)],
|
||||||
|
},
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn modules() {
|
fn modules() {
|
||||||
parse_test_wrap_ast! {
|
parse_test_wrap_ast! {
|
||||||
@ -890,4 +939,3 @@ fn annotations() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,8 +311,11 @@ impl ast::Pattern {
|
|||||||
ast::Pattern::Ignored => {
|
ast::Pattern::Ignored => {
|
||||||
Pattern::Ignored
|
Pattern::Ignored
|
||||||
},
|
},
|
||||||
ast::Pattern::TuplePattern(/*Vec<Pattern>*/..) => {
|
ast::Pattern::TuplePattern(subpatterns) => {
|
||||||
unimplemented!()
|
let pats: Vec<_> = subpatterns.iter().map(|pat| pat.reduce(symbol_table)).collect();
|
||||||
|
let pats: Result<Vec<Pattern>, PatternError> = pats.into_iter().collect();
|
||||||
|
let pats = pats?;
|
||||||
|
Pattern::Tuple(pats)
|
||||||
},
|
},
|
||||||
ast::Pattern::Literal(lit) => Pattern::Literal(match lit {
|
ast::Pattern::Literal(lit) => Pattern::Literal(match lit {
|
||||||
ast::PatternLiteral::NumPattern { neg, num } => match (neg, num) {
|
ast::PatternLiteral::NumPattern { neg, num } => match (neg, num) {
|
||||||
|
@ -125,6 +125,7 @@ pub struct Alternative {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Pattern {
|
pub enum Pattern {
|
||||||
|
Tuple(Vec<Pattern>),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Ignored,
|
Ignored,
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,11 @@ impl<'a> State<'a> {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
|
Pattern::Tuple(subpatterns) => match scrut {
|
||||||
|
Primitive::Tuple(items) if items.len() == subpatterns.len() =>
|
||||||
|
items.iter().zip(subpatterns.iter()).all(|(item, subpat)| matches(item, subpat)),
|
||||||
|
_ => false //TODO should be a type error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cond = self.expression(cond)?;
|
let cond = self.expression(cond)?;
|
||||||
@ -413,6 +418,7 @@ impl<'a> State<'a> {
|
|||||||
(BooleanNot, Lit(Bool(false))) => Bool(true),
|
(BooleanNot, Lit(Bool(false))) => Bool(true),
|
||||||
(Negate, Lit(Nat(n))) => Int(-(*n as i64)),
|
(Negate, Lit(Nat(n))) => Int(-(*n as i64)),
|
||||||
(Negate, Lit(Int(n))) => Int(-(*n as i64)),
|
(Negate, Lit(Int(n))) => Int(-(*n as i64)),
|
||||||
|
(Negate, Lit(Float(f))) => Float(-(*f as f64)),
|
||||||
(Increment, Lit(Int(n))) => Int(*n),
|
(Increment, Lit(Int(n))) => Int(*n),
|
||||||
(Increment, Lit(Nat(n))) => Nat(*n),
|
(Increment, Lit(Nat(n))) => Nat(*n),
|
||||||
_ => return Err("No valid prefix op".into())
|
_ => return Err("No valid prefix op".into())
|
||||||
|
@ -116,6 +116,21 @@ if x {
|
|||||||
eval_assert(&source, expected);
|
eval_assert(&source, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case(r#"(45, "panda", false, 2.2)"#, r#""yes""#)]
|
||||||
|
#[test_case(r#"(99, "panda", false, -2.45)"#, r#""maybe""#)]
|
||||||
|
fn tuple_patterns(input: &str, expected: &str) {
|
||||||
|
let mut source = format!("let x = {}", input);
|
||||||
|
source.push_str(r#"
|
||||||
|
if x {
|
||||||
|
is (45, "pablo", _, 28.4) then "no"
|
||||||
|
is (_, "panda", _, 2.2) then "yes"
|
||||||
|
is _ then "maybe"
|
||||||
|
}"#);
|
||||||
|
println!("{}", source);
|
||||||
|
|
||||||
|
eval_assert(&source, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_is_patterns() {
|
fn if_is_patterns() {
|
||||||
let source = r#"
|
let source = r#"
|
||||||
|
Loading…
Reference in New Issue
Block a user