From e40b8ece3bfecceee6fcd0a1a31a4a3451ef3394 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Mon, 25 Oct 2021 23:26:03 -0700 Subject: [PATCH] Make multi-armed patterns work --- TODO.md | 4 ++++ schala-lang/language/src/reduced_ir/mod.rs | 23 ++++++++++++++++--- .../language/src/tree_walk_eval/mod.rs | 1 - .../language/src/tree_walk_eval/test.rs | 16 ++++++++++++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/TODO.md b/TODO.md index 565629f..ba412e1 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,9 @@ # Immediate TODOs / General Code Cleanup +## Testing + +* Get a test library for running many unit tests working + ## Symbols * Add some good printf-debugging impls for SymbolTable-related items diff --git a/schala-lang/language/src/reduced_ir/mod.rs b/schala-lang/language/src/reduced_ir/mod.rs index a244c6b..68e3641 100644 --- a/schala-lang/language/src/reduced_ir/mod.rs +++ b/schala-lang/language/src/reduced_ir/mod.rs @@ -195,7 +195,25 @@ impl<'a> Reducer<'a> { Expression::CaseMatch { cond, alternatives } }, 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 { Ok(match self { ast::Pattern::Ignored => { - unimplemented!() + Pattern::Ignored }, ast::Pattern::TuplePattern(/*Vec*/..) => { unimplemented!() - }, ast::Pattern::Literal(lit) => Pattern::Literal(match lit { ast::PatternLiteral::NumPattern { neg, num } => match (neg, num) { diff --git a/schala-lang/language/src/tree_walk_eval/mod.rs b/schala-lang/language/src/tree_walk_eval/mod.rs index a41d5eb..a673ba6 100644 --- a/schala-lang/language/src/tree_walk_eval/mod.rs +++ b/schala-lang/language/src/tree_walk_eval/mod.rs @@ -276,7 +276,6 @@ impl<'a> State<'a> { } fn case_match_expression(&mut self, cond: Expression, alternatives: Vec) -> EvalResult { - fn matches(scrut: &Primitive, pat: &Pattern) -> bool { match pat { Pattern::Ignored => true, diff --git a/schala-lang/language/src/tree_walk_eval/test.rs b/schala-lang/language/src/tree_walk_eval/test.rs index 9287920..e83bb07 100644 --- a/schala-lang/language/src/tree_walk_eval/test.rs +++ b/schala-lang/language/src/tree_walk_eval/test.rs @@ -86,7 +86,7 @@ fn basic_if_statement() { } #[test] -fn basic_patterns() { +fn basic_patterns_1() { let source =r#" let x = 10 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)"); } +#[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] fn if_is_patterns() { let source = r#"