Change eval strategy to use conditional sigil

This commit is contained in:
greg 2018-10-29 01:50:43 -07:00
parent d7f0147a4f
commit b8df09e956
2 changed files with 28 additions and 10 deletions

View File

@ -116,6 +116,23 @@ impl Expr {
_ => format!("{:?}", self),
}
}
fn replace_conditional_target_sigil(self, replacement: &Expr) -> Expr {
use self::Expr::*;
match self {
ConditionalTargetSigilValue => replacement.clone(),
Unit | Lit(_) | Func(_) | Val(_) | Constructor { .. } |
CaseMatch { .. } | UnimplementedSigilValue => self,
Tuple(exprs) => Tuple(exprs.into_iter().map(|e| e.replace_conditional_target_sigil(replacement)).collect()),
Call { f, args } => {
let new_args = args.into_iter().map(|e| e.replace_conditional_target_sigil(replacement)).collect();
Call { f, args: new_args }
},
Conditional { .. } => panic!("Dunno if I need this, but if so implement"),
Assign { .. } => panic!("I'm pretty sure I don't need this"),
}
}
}
impl<'a> State<'a> {
@ -194,7 +211,7 @@ impl<'a> State<'a> {
Assign { box val, box expr } => self.assign_expression(val, expr),
Unit => Ok(Node::Expr(Unit)),
CaseMatch { box cond, alternatives } => self.case_match_expression(cond, alternatives),
ConditionalTargetPlaceholder => Err(format!("This value shouldn't exist here")),
ConditionalTargetSigilValue => Ok(Node::Expr(ConditionalTargetSigilValue)),
UnimplementedSigilValue => Err(format!("Sigil value eval not implemented")),
}
}
@ -379,11 +396,12 @@ fn case_match_expression(&mut self, cond: Expr, alternatives: Vec<Alternative>)
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) => {
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())? {
let guard_expr = guard_expr.clone().replace_conditional_target_sigil(&e);
match self.expression(guard_expr.to_node())? {
Node::Expr(Expr::Lit(::reduced_ast::Lit::Bool(true))) =>
return self.block(alt.item),
_ => continue,

View File

@ -48,7 +48,7 @@ pub enum Expr {
then_clause: Vec<Stmt>,
else_clause: Vec<Stmt>,
},
ConditionalTargetPlaceholder,
ConditionalTargetSigilValue,
CaseMatch {
cond: Box<Expr>,
alternatives: Vec<Alternative>
@ -163,7 +163,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
};
let alternatives = vec![
pat.to_alternative(&cond, then_clause, symbol_table),
pat.to_alternative(then_clause, symbol_table),
Alternative::default(else_clause),
];
@ -178,7 +178,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
match arm.guard {
Guard::Pat(ref p) => {
let item = arm.body.iter().map(|expr| expr.reduce(symbol_table)).collect();
let alt = p.to_alternative(&cond, item, symbol_table);
let alt = p.to_alternative(item, symbol_table);
alternatives.push(alt);
},
Guard::HalfExpr(HalfExpr { op: _, expr: _ }) => {
@ -196,7 +196,7 @@ fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody,
impl Pattern {
fn to_alternative(&self, cond: &Box<Expr>, item: Vec<Stmt>, symbol_table: &SymbolTable) -> Alternative {
fn to_alternative(&self, item: Vec<Stmt>, symbol_table: &SymbolTable) -> Alternative {
use self::Pattern::*;
fn handle_symbol(symbol: &Symbol, subpatterns: &Vec<Pattern>, item: Vec<Stmt>) -> Alternative {
@ -253,7 +253,7 @@ impl Pattern {
});
let guard = Some(Expr::Call {
f: Box::new(Expr::Func(Func::BuiltIn(Rc::new("==".to_string())))),
args: vec![comparison, *cond.clone()]
args: vec![comparison, Expr::ConditionalTargetSigilValue],
});
Alternative {
tag: None,
@ -266,11 +266,11 @@ impl Pattern {
PatternLiteral::StringPattern(_s) => unimplemented!(),
PatternLiteral::BoolPattern(b) => {
let guard = Some(if *b {
*cond.clone()
Expr::ConditionalTargetSigilValue
} else {
Expr::Call {
f: Box::new(Expr::Func(Func::BuiltIn(Rc::new("!".to_string())))),
args: vec![*cond.clone()]
args: vec![Expr::ConditionalTargetSigilValue]
}
});
Alternative {