case_match_expression split out into its own method
This commit is contained in:
parent
40ccea8c05
commit
f2282f0101
@ -7,7 +7,7 @@ use std::io;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use util::ScopeStack;
|
use util::ScopeStack;
|
||||||
use reduced_ast::{ReducedAST, Stmt, Expr, Lit, Func};
|
use reduced_ast::{ReducedAST, Stmt, Expr, Lit, Func, Alternative};
|
||||||
use symbol_table::{SymbolSpec, Symbol, SymbolTable};
|
use symbol_table::{SymbolSpec, Symbol, SymbolTable};
|
||||||
|
|
||||||
pub struct State<'a> {
|
pub struct State<'a> {
|
||||||
@ -193,49 +193,7 @@ impl<'a> State<'a> {
|
|||||||
Conditional { box cond, then_clause, else_clause } => self.conditional(cond, then_clause, else_clause),
|
Conditional { box cond, then_clause, else_clause } => self.conditional(cond, then_clause, else_clause),
|
||||||
Assign { box val, box expr } => self.assign_expression(val, expr),
|
Assign { box val, box expr } => self.assign_expression(val, expr),
|
||||||
Unit => Ok(Node::Expr(Unit)),
|
Unit => Ok(Node::Expr(Unit)),
|
||||||
CaseMatch { box cond, alternatives } => match self.expression(Node::Expr(cond))? {
|
CaseMatch { box cond, alternatives } => self.case_match_expression(cond, alternatives),
|
||||||
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_scope(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() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(guard_expr) = alt.guard {
|
|
||||||
let evaled_guard = inner_state.expression(guard_expr.to_node());
|
|
||||||
println!("EVALED GUARD: {:?}", evaled_guard);
|
|
||||||
//continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return inner_state.block(alt.item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(format!("PrimObject failed pattern match"));
|
|
||||||
},
|
|
||||||
Node::PrimTuple { .. } => Err(format!("Tuples not implemented")), //TODO make a distinction between not yet implemented and an actual runtime error
|
|
||||||
Node::Expr(e) => {
|
|
||||||
for alt in alternatives {
|
|
||||||
match (alt.guard, alt.tag) {
|
|
||||||
(Some(ref guard_expr), None) => {
|
|
||||||
match self.expression(guard_expr.clone().to_node())? {
|
|
||||||
Node::Expr(Expr::Lit(::reduced_ast::Lit::Bool(true))) =>
|
|
||||||
return self.block(alt.item),
|
|
||||||
_ => continue,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(None, None) => return self.block(alt.item),
|
|
||||||
_ => return Err(format!("Shouldn't match an expr against a pattern"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(format!("Expr Failed pattern match"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UnimplementedSigilValue => Err(format!("Sigil value eval not implemented"))
|
UnimplementedSigilValue => Err(format!("Sigil value eval not implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,6 +351,53 @@ impl<'a> State<'a> {
|
|||||||
Ok(Node::Expr(Expr::Unit))
|
Ok(Node::Expr(Expr::Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>) -> EvalResult<Node> {
|
||||||
|
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_scope(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() });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(guard_expr) = alt.guard {
|
||||||
|
let evaled_guard = inner_state.expression(guard_expr.to_node());
|
||||||
|
println!("EVALED GUARD: {:?}", evaled_guard);
|
||||||
|
//continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return inner_state.block(alt.item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(format!("PrimObject failed pattern match"));
|
||||||
|
},
|
||||||
|
Node::PrimTuple { .. } => Err(format!("Tuples not implemented")), //TODO make a distinction between not yet implemented and an actual runtime error
|
||||||
|
Node::Expr(e) => {
|
||||||
|
for alt in alternatives {
|
||||||
|
match (alt.guard, alt.tag) {
|
||||||
|
(Some(ref guard_expr), None) => {
|
||||||
|
match self.expression(guard_expr.clone().to_node())? {
|
||||||
|
Node::Expr(Expr::Lit(::reduced_ast::Lit::Bool(true))) =>
|
||||||
|
return self.block(alt.item),
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(None, None) => return self.block(alt.item),
|
||||||
|
_ => return Err(format!("Shouldn't match an expr against a pattern"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(format!("Expr Failed pattern match"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn value(&mut self, name: Rc<String>) -> EvalResult<Node> {
|
fn value(&mut self, name: Rc<String>) -> EvalResult<Node> {
|
||||||
use self::ValueEntry::*;
|
use self::ValueEntry::*;
|
||||||
use self::Func::*;
|
use self::Func::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user