@@ -38,9 +38,6 @@ pub trait CallableFormals {
38
38
pub trait Callable : CallableFormals {
39
39
fn match_args ( & self , args : List , stack : & mut CallStack ) -> Result < ( List , List ) , Signal > {
40
40
let mut formals = self . formals ( ) ;
41
-
42
- // this collects the expressions
43
- let mut expr_ellipsis: ExprList = ExprList :: new ( ) ;
44
41
let mut ellipsis: List = List :: new ( ) ;
45
42
let mut matched_args: List = List :: new ( ) ;
46
43
@@ -70,52 +67,56 @@ pub trait Callable: CallableFormals {
70
67
71
68
// backfill unnamed args, populating ellipsis with overflow
72
69
for ( key, value) in args. iter_pairs ( ) {
73
- match ( key, value . clone ( ) ) {
70
+ match key {
74
71
// 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) ,
79
73
80
74
// unnamed args populate next formal, or ellipsis if formals exhausted
81
- ( Character :: NA , value ) => {
75
+ Character :: NA => {
82
76
let next_unassigned_formal = formals. remove ( 0 ) ;
83
77
if let Some ( ( Some ( param) , _) ) = next_unassigned_formal {
84
78
matched_args. push_named ( Character :: Some ( param) , value) ;
85
79
} else {
86
- let Obj :: Promise ( _, e, _) = value. clone ( ) else {
87
- unreachable ! ( )
88
- } ;
89
- expr_ellipsis. push_named ( Character :: NA . as_option ( ) , e) ;
90
80
ellipsis. push_named ( Character :: NA , value) ;
91
81
}
92
82
}
93
- _ => unreachable ! ( ) ,
94
83
}
95
84
}
96
85
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 ( ) ;
104
87
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
+ }
106
96
107
- let list = BUILTIN . get ( "list" ) . cloned ( ) . unwrap ( ) ;
97
+ let list = crate :: callable:: builtins:: BUILTIN
98
+ . get ( "list" )
99
+ . cloned ( )
100
+ . unwrap ( ) ;
108
101
109
102
// convert the expr_ellipsis to an Obj::Promise where the expression is a call into List
110
103
111
- let a = Obj :: Promise (
104
+ let ellipsis_promise = Obj :: Promise (
112
105
None ,
113
- Expr :: Call ( Box :: new ( Expr :: Primitive ( list) ) , expr_ellipsis ) ,
106
+ Expr :: Call ( Box :: new ( Expr :: Primitive ( list) ) , ellipsis_expr ) ,
114
107
stack. last_frame ( ) . env ( ) . clone ( ) ,
115
108
) ;
116
109
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
+
117
118
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 ) ;
119
120
} else if !remainder. is_empty ( ) {
120
121
matched_args. push_named (
121
122
Character :: Some ( "..." . to_string ( ) ) ,
0 commit comments