summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-04-19 17:51:33 +0200
committerLaurenz <laurmaedje@gmail.com>2023-04-19 17:51:33 +0200
commitf08ae95b9d8be5165f9c8cac4c755d0510c3a18a (patch)
treecc4bdf617618535d128e1a5611f270c8a99df31f /src/eval
parent5a6330dbfce9ed30c77502b66db843fd72b2d267 (diff)
Fix argument sinks
Fixes #886.
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/args.rs21
-rw-r--r--src/eval/scope.rs8
2 files changed, 19 insertions, 10 deletions
diff --git a/src/eval/args.rs b/src/eval/args.rs
index 8617bd93..bea2baa1 100644
--- a/src/eval/args.rs
+++ b/src/eval/args.rs
@@ -62,14 +62,23 @@ impl Args {
}
/// Consume n positional arguments if possible.
- pub fn consume(&mut self, n: usize) -> SourceResult<EcoVec<Arg>> {
- if n > self.items.len() {
+ pub fn consume(&mut self, n: usize) -> SourceResult<Vec<Arg>> {
+ let mut list = vec![];
+
+ let mut i = 0;
+ while i < self.items.len() && list.len() < n {
+ if self.items[i].name.is_none() {
+ list.push(self.items.remove(i));
+ } else {
+ i += 1;
+ }
+ }
+
+ if list.len() < n {
bail!(self.span, "not enough arguments");
}
- let vec = self.items.to_vec();
- let (left, right) = vec.split_at(n);
- self.items = right.into();
- Ok(left.into())
+
+ Ok(list)
}
/// Consume and cast the first positional argument.
diff --git a/src/eval/scope.rs b/src/eval/scope.rs
index f2207188..76633bf2 100644
--- a/src/eval/scope.rs
+++ b/src/eval/scope.rs
@@ -38,20 +38,20 @@ impl<'a> Scopes<'a> {
/// Try to access a variable immutably.
pub fn get(&self, var: &str) -> StrResult<&Value> {
- Ok(std::iter::once(&self.top)
+ std::iter::once(&self.top)
.chain(self.scopes.iter().rev())
.chain(self.base.map(|base| base.global.scope()))
.find_map(|scope| scope.get(var))
- .ok_or(eco_format!("unknown variable: {}", var))?)
+ .ok_or_else(|| eco_format!("unknown variable: {}", var))
}
/// Try to access a variable immutably in math.
pub fn get_in_math(&self, var: &str) -> StrResult<&Value> {
- Ok(std::iter::once(&self.top)
+ std::iter::once(&self.top)
.chain(self.scopes.iter().rev())
.chain(self.base.map(|base| base.math.scope()))
.find_map(|scope| scope.get(var))
- .ok_or(eco_format!("unknown variable: {}", var))?)
+ .ok_or_else(|| eco_format!("unknown variable: {}", var))
}
/// Try to access a variable mutably.