summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-31 22:43:11 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-31 22:43:11 +0100
commit6fcef9973be4253e5b377251dd9d1921f9738fc1 (patch)
treeb849a6a8707d207c5cec5a1dcbeb60e4bf52b73c /src
parente3139ed3ee8c96b89f7f10f4ed72b4893d724689 (diff)
Refresh tests 🔄
Diffstat (limited to 'src')
-rw-r--r--src/eval/mod.rs50
-rw-r--r--src/eval/ops.rs6
-rw-r--r--src/parse/parser.rs2
3 files changed, 43 insertions, 15 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,
}
}
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 2ca8eb10..b7767772 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -205,7 +205,7 @@ impl<'s> Parser<'s> {
pub fn expect(&mut self, t: Token) -> bool {
let eaten = self.eat_if(t);
if !eaten {
- self.expected(t.name());
+ self.expected_at(t.name(), self.last_end);
}
eaten
}