Basic pattern matching working
This commit is contained in:
parent
6833bc4f00
commit
897c1181a9
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::fmt::Write;
|
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> {
|
impl<'a> State<'a> {
|
||||||
pub fn new(symbol_table_handle: Rc<RefCell<SymbolTable>>) -> State<'a> {
|
pub fn new(symbol_table_handle: Rc<RefCell<SymbolTable>>) -> State<'a> {
|
||||||
let mut values = StateStack::new(Some(format!("global")));
|
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)),
|
other => return Err(format!("Tried to call {:?} which is not a function or data constructor", other)),
|
||||||
},
|
},
|
||||||
Val(v) => self.value(v),
|
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)),
|
constructor @ Constructor { .. } => Ok(Node::Expr(constructor)),
|
||||||
func @ Func(_) => Ok(Node::Expr(func)),
|
func @ Func(_) => Ok(Node::Expr(func)),
|
||||||
Tuple(exprs) => {
|
Tuple(exprs) => {
|
||||||
@ -210,7 +213,27 @@ impl<'a> State<'a> {
|
|||||||
Ok(Node::Expr(Expr::Unit))
|
Ok(Node::Expr(Expr::Unit))
|
||||||
},
|
},
|
||||||
Unit => Ok(Node::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"))
|
UnimplementedSigilValue => Err(format!("Sigil value eval not implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,9 @@ pub enum Expr {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Alternative {
|
pub struct Alternative {
|
||||||
tag: Option<usize>,
|
pub tag: Option<usize>,
|
||||||
bound_vars: Vec<Rc<String>>,
|
pub bound_vars: Vec<Option<Rc<String>>>, //remember that order matters here
|
||||||
item: Vec<Stmt>,
|
pub item: Vec<Stmt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -160,8 +160,9 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
|
|||||||
SymbolSpec::DataConstructor { index, .. } => index.clone(),
|
SymbolSpec::DataConstructor { index, .. } => index.clone(),
|
||||||
_ => panic!("Bad symbol"),
|
_ => 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::Literal(PatternLiteral::VarPattern(var)) => Some(var.clone()),
|
||||||
|
Pattern::Ignored => None,
|
||||||
_ => None,
|
_ => None,
|
||||||
}).collect();
|
}).collect();
|
||||||
Alternative {
|
Alternative {
|
||||||
|
Loading…
Reference in New Issue
Block a user