From 897c1181a9d502e38fe913df1135aacc85a4b472 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 14 Aug 2018 21:17:43 -0700 Subject: [PATCH] Basic pattern matching working --- schala-lang/src/eval.rs | 25 ++++++++++++++++++++++++- schala-lang/src/reduced_ast.rs | 9 +++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index 914ec34..ad27aec 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -1,3 +1,4 @@ + use std::cell::RefCell; use std::rc::Rc; use std::fmt::Write; @@ -20,6 +21,7 @@ macro_rules! builtin_binding { } } +//TODO add a more concise way of getting a new frame impl<'a> State<'a> { pub fn new(symbol_table_handle: Rc>) -> State<'a> { let mut values = StateStack::new(Some(format!("global"))); @@ -185,6 +187,7 @@ impl<'a> State<'a> { other => return Err(format!("Tried to call {:?} which is not a function or data constructor", other)), }, Val(v) => self.value(v), + Constructor { arity, ref name, tag, .. } if arity == 0 => Ok(Node::PrimObject { name: name.clone(), tag, items: vec![] }), constructor @ Constructor { .. } => Ok(Node::Expr(constructor)), func @ Func(_) => Ok(Node::Expr(func)), Tuple(exprs) => { @@ -210,7 +213,27 @@ impl<'a> State<'a> { Ok(Node::Expr(Expr::Unit)) }, Unit => Ok(Node::Expr(Unit)), - CaseMatch { cond, alternatives } => unimplemented!(), + CaseMatch { box cond, alternatives } => match self.expression(Node::Expr(cond))? { + Node::PrimObject { name, tag, items } => { + for alt in alternatives { + if alt.tag.map(|t| t == tag).unwrap_or(true) { + let mut inner_state = State { + values: self.values.new_frame(None), + symbol_table_handle: self.symbol_table_handle.clone(), + }; + for (bound_var, val) in alt.bound_vars.iter().zip(items.iter()) { + if let Some(bv) = bound_var.as_ref() { + inner_state.values.insert(bv.clone(), ValueEntry::Binding { constant: true, val: val.clone() }); + } + } + return inner_state.block(alt.item) + } + } + return Err(format!("No matches found")); + }, + Node::PrimTuple { .. } => Err(format!("Tuples don't work")), + Node::Expr(e) => Err(format!("Exprs don't work {:?}", e)) + }, UnimplementedSigilValue => Err(format!("Sigil value eval not implemented")) } } diff --git a/schala-lang/src/reduced_ast.rs b/schala-lang/src/reduced_ast.rs index 74853b2..596a590 100644 --- a/schala-lang/src/reduced_ast.rs +++ b/schala-lang/src/reduced_ast.rs @@ -57,9 +57,9 @@ pub enum Expr { #[derive(Debug, Clone)] pub struct Alternative { - tag: Option, - bound_vars: Vec>, - item: Vec, + pub tag: Option, + pub bound_vars: Vec>>, //remember that order matters here + pub item: Vec, } #[derive(Debug, Clone)] @@ -160,8 +160,9 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, SymbolSpec::DataConstructor { index, .. } => index.clone(), _ => panic!("Bad symbol"), }; - let bound_vars = subpatterns.iter().flat_map(|p| match p { + let bound_vars = subpatterns.iter().map(|p| match p { Pattern::Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()), + Pattern::Ignored => None, _ => None, }).collect(); Alternative {