Skip to content

Commit 0ba583d

Browse files
committed
...
1 parent 5a6bd88 commit 0ba583d

File tree

2 files changed

+38
-26
lines changed

2 files changed

+38
-26
lines changed

src/CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616

1717
## Noteable Bugs Addressed:
1818

19+
<<<<<<< Updated upstream
1920
* `substitute()` now works on datatypes such as literals or calls.
21+
=======
22+
* `substitute()` now works on datatypes such as literals or calls (#199).
23+
* accessing variable collected via 'rest-args' does now force evaluation of calls (#216).
24+
>>>>>>> Stashed changes
2025
2126
## Internals
2227

@@ -26,9 +31,15 @@
2631
and unused ones removed.
2732
* The `RepType` struct that was introduced in 0.4.0 was removed again (#189).
2833
* `eval_list_eager()` was removed from the `Context` trait and added as a member method for `CallStack`.
34+
<<<<<<< Updated upstream
2935
* `eval_list_lazy()` now boxes all expressions in promises (including literals)
3036
This is necessary to box `..a`-style ellipsis arguments in a list-call promise, which requires
3137
access to the underlying expression.
38+
=======
39+
* `eval_list_lazy()` now boxes all expressions in promises (including literals).
40+
This is necessary to box `..a`-style ellipsis arguments in a list-call promise, which requires
41+
access to the underlying expression (needed to solve #216).
42+
>>>>>>> Stashed changes
3243
3344
## Notable Bugs Addressed
3445

src/callable/core.rs

+27-26
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ pub trait CallableFormals {
3838
pub trait Callable: CallableFormals {
3939
fn match_args(&self, args: List, stack: &mut CallStack) -> Result<(List, List), Signal> {
4040
let mut formals = self.formals();
41-
42-
// this collects the expressions
43-
let mut expr_ellipsis: ExprList = ExprList::new();
4441
let mut ellipsis: List = List::new();
4542
let mut matched_args: List = List::new();
4643

@@ -70,52 +67,56 @@ pub trait Callable: CallableFormals {
7067

7168
// backfill unnamed args, populating ellipsis with overflow
7269
for (key, value) in args.iter_pairs() {
73-
match (key, value.clone()) {
70+
match key {
7471
// named args go directly to ellipsis, they did not match a formal
75-
(Character::Some(arg), Obj::Promise(_, e, _)) => {
76-
expr_ellipsis.push_named(Character::Some(arg.clone()).as_option(), e);
77-
ellipsis.push_named(Character::Some(arg), value);
78-
}
72+
Character::Some(arg) => ellipsis.push_named(Character::Some(arg), value),
7973

8074
// unnamed args populate next formal, or ellipsis if formals exhausted
81-
(Character::NA, value) => {
75+
Character::NA => {
8276
let next_unassigned_formal = formals.remove(0);
8377
if let Some((Some(param), _)) = next_unassigned_formal {
8478
matched_args.push_named(Character::Some(param), value);
8579
} else {
86-
let Obj::Promise(_, e, _) = value.clone() else {
87-
unreachable!()
88-
};
89-
expr_ellipsis.push_named(Character::NA.as_option(), e);
9080
ellipsis.push_named(Character::NA, value);
9181
}
9282
}
93-
_ => unreachable!(),
9483
}
9584
}
9685

97-
// add back in parameter defaults that weren't filled with args
98-
for (param, default) in formals.into_iter() {
99-
matched_args.push_named(
100-
param.into(),
101-
Obj::Promise(None, default, stack.last_frame().env().clone()),
102-
)
103-
}
86+
let mut ellipsis_expr = ExprList::new();
10487

105-
use crate::callable::builtins::BUILTIN;
88+
for (k, v) in ellipsis.iter_pairs() {
89+
if let Obj::Promise(_, e, _) = v {
90+
ellipsis_expr.push_named(k.as_option(), e)
91+
} else {
92+
// all arguments must be boxed in promises to allow for NSE
93+
unreachable!()
94+
}
95+
}
10696

107-
let list = BUILTIN.get("list").cloned().unwrap();
97+
let list = crate::callable::builtins::BUILTIN
98+
.get("list")
99+
.cloned()
100+
.unwrap();
108101

109102
// convert the expr_ellipsis to an Obj::Promise where the expression is a call into List
110103

111-
let a = Obj::Promise(
104+
let ellipsis_promise = Obj::Promise(
112105
None,
113-
Expr::Call(Box::new(Expr::Primitive(list)), expr_ellipsis),
106+
Expr::Call(Box::new(Expr::Primitive(list)), ellipsis_expr),
114107
stack.last_frame().env().clone(),
115108
);
116109

110+
// add back in parameter defaults that weren't filled with args
111+
for (param, default) in formals.into_iter() {
112+
matched_args.push_named(
113+
param.into(),
114+
Obj::Promise(None, default, stack.last_frame().env().clone()),
115+
)
116+
}
117+
117118
if let Some(Expr::Ellipsis(Some(name))) = remainder.get(0) {
118-
matched_args.push_named(Character::Some(name), a);
119+
matched_args.push_named(Character::Some(name), ellipsis_promise);
119120
} else if !remainder.is_empty() {
120121
matched_args.push_named(
121122
Character::Some("...".to_string()),

0 commit comments

Comments
 (0)