@@ -12,9 +12,11 @@ use crate::{
12
12
} ;
13
13
14
14
#[ allow( clippy:: too_many_lines) ]
15
+ #[ allow( unused_variables) ]
15
16
pub fn destruct (
16
17
d : & Destruct ,
17
18
parent : Thunk < Val > ,
19
+ fctx : Pending < Context > ,
18
20
new_bindings : & mut GcHashMap < IStr , Thunk < Val > > ,
19
21
) -> Result < ( ) > {
20
22
match d {
@@ -89,6 +91,7 @@ pub fn destruct(
89
91
full: full. clone( ) ,
90
92
index: i,
91
93
} ) ) ,
94
+ fctx. clone ( ) ,
92
95
new_bindings,
93
96
) ?;
94
97
}
@@ -119,6 +122,7 @@ pub fn destruct(
119
122
start: start. len( ) ,
120
123
end: end. len( ) ,
121
124
} ) ) ,
125
+ fctx. clone ( ) ,
122
126
new_bindings,
123
127
) ?;
124
128
}
@@ -151,6 +155,7 @@ pub fn destruct(
151
155
index: i,
152
156
end: end. len( ) ,
153
157
} ) ) ,
158
+ fctx. clone ( ) ,
154
159
new_bindings,
155
160
) ?;
156
161
}
@@ -189,36 +194,51 @@ pub fn destruct(
189
194
Ok ( obj)
190
195
}
191
196
}
192
- let field_names: Vec < _ > = fields. iter ( ) . map ( |f| f. 0 . clone ( ) ) . collect ( ) ;
197
+ let field_names: Vec < _ > = fields
198
+ . iter ( )
199
+ . filter ( |f| f. 2 . is_none ( ) )
200
+ . map ( |f| f. 0 . clone ( ) )
201
+ . collect ( ) ;
193
202
let full = Thunk :: new ( tb ! ( DataThunk {
194
203
parent,
195
204
field_names: field_names. clone( ) ,
196
205
has_rest: rest. is_some( )
197
206
} ) ) ;
198
207
199
- for ( field, d) in fields {
208
+ for ( field, d, default ) in fields {
200
209
#[ derive( Trace ) ]
201
210
struct FieldThunk {
202
211
full : Thunk < ObjValue > ,
203
212
field : IStr ,
213
+ default : Option < ( Pending < Context > , LocExpr ) > ,
204
214
}
205
215
impl ThunkValue for FieldThunk {
206
216
type Output = Val ;
207
217
208
218
fn get ( self : Box < Self > , s : State ) -> Result < Self :: Output > {
209
219
let full = self . full . evaluate ( s. clone ( ) ) ?;
210
- let field = full. get ( s, self . field ) ?. expect ( "shape is checked" ) ;
211
- Ok ( field)
220
+ if let Some ( field) = full. get ( s. clone ( ) , self . field ) ? {
221
+ Ok ( field)
222
+ } else {
223
+ let ( fctx, expr) = self . default . as_ref ( ) . expect ( "shape is checked" ) ;
224
+ Ok ( evaluate ( s, fctx. clone ( ) . unwrap ( ) , & expr) ?)
225
+ }
212
226
}
213
227
}
214
228
let value = Thunk :: new ( tb ! ( FieldThunk {
215
229
full: full. clone( ) ,
216
- field: field. clone( )
230
+ field: field. clone( ) ,
231
+ default : default . clone( ) . map( |e| ( fctx. clone( ) , e) ) ,
217
232
} ) ) ;
218
233
if let Some ( d) = d {
219
- destruct ( d, value, new_bindings) ?;
234
+ destruct ( d, value, fctx . clone ( ) , new_bindings) ?;
220
235
} else {
221
- destruct ( & Destruct :: Full ( field. clone ( ) ) , value, new_bindings) ?;
236
+ destruct (
237
+ & Destruct :: Full ( field. clone ( ) ) ,
238
+ value,
239
+ fctx. clone ( ) ,
240
+ new_bindings,
241
+ ) ?;
222
242
}
223
243
}
224
244
}
@@ -251,10 +271,10 @@ pub fn evaluate_dest(
251
271
}
252
272
let data = Thunk :: new ( tb ! ( EvaluateThunkValue {
253
273
name: into. name( ) ,
254
- fctx,
274
+ fctx: fctx . clone ( ) ,
255
275
expr: value. clone( ) ,
256
276
} ) ) ;
257
- destruct ( into, data, new_bindings) ?;
277
+ destruct ( into, data, fctx , new_bindings) ?;
258
278
}
259
279
BindSpec :: Function {
260
280
name,
0 commit comments