Make multi-armed patterns work

This commit is contained in:
Greg Shuflin 2021-10-25 23:26:03 -07:00
parent 899a4df55e
commit e40b8ece3b
4 changed files with 39 additions and 5 deletions

View File

@ -1,5 +1,9 @@
# Immediate TODOs / General Code Cleanup # Immediate TODOs / General Code Cleanup
## Testing
* Get a test library for running many unit tests working
## Symbols ## Symbols
* Add some good printf-debugging impls for SymbolTable-related items * Add some good printf-debugging impls for SymbolTable-related items

View File

@ -195,7 +195,25 @@ impl<'a> Reducer<'a> {
Expression::CaseMatch { cond, alternatives } Expression::CaseMatch { cond, alternatives }
}, },
CondList(ref condition_arms) => { CondList(ref condition_arms) => {
Expression::ReductionError("if expr".to_string()) let mut alternatives = vec![];
for arm in condition_arms {
match arm.condition {
ast::Condition::Expression(ref _expr) => return Expression::ReductionError("case-expression".to_string()),
ast::Condition::Pattern(ref pat) => {
let alt = Alternative {
pattern: match pat.reduce(self.symbol_table) {
Ok(p) => p,
Err(e) => return Expression::ReductionError(format!("Bad pattern: {:?}", e)),
},
item: self.function_internal_block(&arm.body),
};
alternatives.push(alt);
},
ast::Condition::TruncatedOp(_, _) => return Expression::ReductionError("case-expression-trunc-op".to_string()),
ast::Condition::Else => return Expression::ReductionError("case-expression-else".to_string()),
}
}
Expression::CaseMatch { cond, alternatives }
} }
} }
} }
@ -291,11 +309,10 @@ impl ast::Pattern {
fn reduce(&self, symbol_table: &SymbolTable) -> Result<Pattern, PatternError> { fn reduce(&self, symbol_table: &SymbolTable) -> Result<Pattern, PatternError> {
Ok(match self { Ok(match self {
ast::Pattern::Ignored => { ast::Pattern::Ignored => {
unimplemented!() Pattern::Ignored
}, },
ast::Pattern::TuplePattern(/*Vec<Pattern>*/..) => { ast::Pattern::TuplePattern(/*Vec<Pattern>*/..) => {
unimplemented!() unimplemented!()
}, },
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) {

View File

@ -276,7 +276,6 @@ impl<'a> State<'a> {
} }
fn case_match_expression(&mut self, cond: Expression, alternatives: Vec<Alternative>) -> EvalResult<Primitive> { fn case_match_expression(&mut self, cond: Expression, alternatives: Vec<Alternative>) -> EvalResult<Primitive> {
fn matches(scrut: &Primitive, pat: &Pattern) -> bool { fn matches(scrut: &Primitive, pat: &Pattern) -> bool {
match pat { match pat {
Pattern::Ignored => true, Pattern::Ignored => true,

View File

@ -86,7 +86,7 @@ fn basic_if_statement() {
} }
#[test] #[test]
fn basic_patterns() { fn basic_patterns_1() {
let source =r#" let source =r#"
let x = 10 let x = 10
let a = if x is 10 then { 255 } else { 256 } let a = if x is 10 then { 255 } else { 256 }
@ -98,6 +98,20 @@ let d = if "xxx" is "yyy" then { 20 } else { 30 }
eval_assert(source, "(255, 256, 10, 30)"); eval_assert(source, "(255, 256, 10, 30)");
} }
#[test]
fn basic_patterns_2() {
let source = r#"
let x = "hella"
if x {
is "sanchez" then 23
is "mouri" then 99
is "hella" then 2
is _ then 94
}
"#;
eval_assert(source, "2");
}
#[test] #[test]
fn if_is_patterns() { fn if_is_patterns() {
let source = r#" let source = r#"