diff options
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/mod.rs | 50 | ||||
| -rw-r--r-- | src/eval/ops.rs | 6 |
2 files changed, 42 insertions, 14 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs index a43219e7..1a211670 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -317,17 +317,11 @@ impl Spanned<&ExprBinary> { return Value::Error; } - let lhty = lhs.type_name(); - let rhty = rhs.type_name(); + let (l, r) = (lhs.type_name(), rhs.type_name()); + let out = op(lhs, rhs); if out == Value::Error { - ctx.diag(error!( - self.span, - "cannot apply '{}' to {} and {}", - self.v.op.v.as_str(), - lhty, - rhty, - )); + self.error(ctx, l, r); } out @@ -358,13 +352,41 @@ impl Spanned<&ExprBinary> { } }; - if let Ok(mut slot) = slot.try_borrow_mut() { - *slot = op(std::mem::take(&mut slot), rhs); - return Value::None; + let (constant, err, value) = if let Ok(mut inner) = slot.try_borrow_mut() { + let lhs = std::mem::take(&mut *inner); + let types = (lhs.type_name(), rhs.type_name()); + + *inner = op(lhs, rhs); + if *inner == Value::Error { + (false, Some(types), Value::Error) + } else { + (false, None, Value::None) + } + } else { + (true, None, Value::Error) + }; + + if constant { + ctx.diag(error!(span, "cannot assign to a constant")); } - ctx.diag(error!(span, "cannot assign to a constant")); - Value::Error + if let Some((l, r)) = err { + self.error(ctx, l, r); + } + + value + } + + fn error(&self, ctx: &mut EvalContext, l: &str, r: &str) { + let op = self.v.op.v.as_str(); + let message = match self.v.op.v { + BinOp::Add => format!("cannot add {} and {}", l, r), + BinOp::Sub => format!("cannot subtract {1} from {0}", l, r), + BinOp::Mul => format!("cannot multiply {} with {}", l, r), + BinOp::Div => format!("cannot divide {} by {}", l, r), + _ => format!("cannot apply '{}' to {} and {}", op, l, r), + }; + ctx.diag(error!(self.span, "{}", message)); } } diff --git a/src/eval/ops.rs b/src/eval/ops.rs index 56d6687b..c52a62ca 100644 --- a/src/eval/ops.rs +++ b/src/eval/ops.rs @@ -44,10 +44,16 @@ pub fn add(lhs: Value, rhs: Value) -> Value { (Linear(a), Length(b)) => Linear(a + b), (Linear(a), Relative(b)) => Linear(a + b), (Linear(a), Linear(b)) => Linear(a + b), + (Str(a), Str(b)) => Str(a + &b), (Array(a), Array(b)) => Array(concat(a, b)), (Dict(a), Dict(b)) => Dict(concat(a, b)), + + // TODO: Add string and template. (Template(a), Template(b)) => Template(concat(a, b)), + (Template(a), None) => Template(a), + (None, Template(b)) => Template(b), + _ => Error, } } |
