summaryrefslogtreecommitdiff
path: root/src/eval/ops.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval/ops.rs')
-rw-r--r--src/eval/ops.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/eval/ops.rs b/src/eval/ops.rs
index 732bfb14..e40fa78d 100644
--- a/src/eval/ops.rs
+++ b/src/eval/ops.rs
@@ -1,7 +1,9 @@
use std::cmp::Ordering;
+use std::convert::TryFrom;
use super::Value;
use crate::diag::StrResult;
+use crate::util::EcoString;
use Value::*;
/// Bail with a type mismatch error.
@@ -150,8 +152,8 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult<Value> {
(Fractional(a), Float(b)) => Fractional(a * b),
(Int(a), Fractional(b)) => Fractional(a as f64 * b),
- (Str(a), Int(b)) => Str(a.repeat(b)?),
- (Int(a), Str(b)) => Str(b.repeat(a)?),
+ (Str(a), Int(b)) => Str(repeat_str(a, b)?),
+ (Int(a), Str(b)) => Str(repeat_str(b, a)?),
(Array(a), Int(b)) => Array(a.repeat(b)?),
(Int(a), Array(b)) => Array(b.repeat(a)?),
(Template(a), Int(b)) => Template(a.repeat(b)?),
@@ -161,6 +163,16 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult<Value> {
})
}
+/// Repeat a string a number of times.
+fn repeat_str(string: EcoString, n: i64) -> StrResult<EcoString> {
+ let n = usize::try_from(n)
+ .ok()
+ .and_then(|n| string.len().checked_mul(n).map(|_| n))
+ .ok_or_else(|| format!("cannot repeat this string {} times", n))?;
+
+ Ok(string.repeat(n))
+}
+
/// Compute the quotient of two values.
pub fn div(lhs: Value, rhs: Value) -> StrResult<Value> {
Ok(match (lhs, rhs) {