1
1
//! List object
2
2
use super :: { BoxedObject , Iter , Object , RefValue } ;
3
+ use crate :: value;
3
4
use tokay_macros:: tokay_method;
4
5
extern crate self as tokay;
5
6
@@ -92,7 +93,9 @@ impl List {
92
93
if let Some ( list) = borrowed. object:: <List >( ) {
93
94
Ok ( RefValue :: from( list. clone( ) ) )
94
95
} else {
95
- Ok ( RefValue :: from( List { list: vec![ list. clone( ) ] } ) )
96
+ Ok ( RefValue :: from( List {
97
+ list: vec![ list. clone( ) ] ,
98
+ } ) )
96
99
}
97
100
} ) ;
98
101
@@ -101,6 +104,8 @@ impl List {
101
104
102
105
Ok ( RefValue :: from( if let Some ( list) = list. object:: <List >( ) {
103
106
list. len( )
107
+ } else if list. is_void( ) {
108
+ 0
104
109
} else {
105
110
1
106
111
} ) )
@@ -184,7 +189,7 @@ impl List {
184
189
}
185
190
}
186
191
187
- // Extend in-place when possible.
192
+ // Append or extend in-place when possible.
188
193
if let ( Ok ( mut inner) , Ok ( to_append) ) = ( list. try_borrow_mut( ) , append. try_borrow( ) ) {
189
194
let inner = inner. object_mut:: <List >( ) . unwrap( ) ;
190
195
@@ -218,7 +223,7 @@ impl List {
218
223
219
224
// In case list is not a list, make it a list.
220
225
if !list. is( "list" ) {
221
- list = Self :: list ( vec! [ list] , None ) ? ;
226
+ list = RefValue :: from ( List :: from ( list) ) ;
222
227
}
223
228
224
229
let mut list = list. borrow( ) . object:: <List >( ) . unwrap( ) . clone( ) ;
@@ -238,22 +243,20 @@ impl List {
238
243
Ok ( RefValue :: from( list) )
239
244
} ) ;
240
245
246
+ /** Explicitly pushes `item` to `list`.
247
+
248
+ When `index` is provided, the value is inserted at the given offset,
249
+ otherwise it is appended (pushed) to the list's end. */
241
250
tokay_method ! ( "list_push : @list, item, index=void" , {
242
251
// Don't push void
243
252
if item. is_void( ) {
244
- return Ok ( list ) ;
253
+ return Ok ( value! [ void ] ) ;
245
254
}
246
255
247
- // In case list is not a list, make it a list.
248
- if !list. is( "list" ) {
249
- list = Self :: list( vec![ list] , None ) ?;
250
- }
251
-
252
- // list_push returns the list itself, therefore this block.
253
- {
254
- let mut list = list. borrow_mut( ) ;
255
- let list = list. object_mut:: <List >( ) . unwrap( ) ;
256
+ let mut list = list. borrow_mut( ) ;
256
257
258
+ // If first parameter is not a list, just do nothing!
259
+ if let Some ( list) = list. object_mut:: <List >( ) {
257
260
if index. is_void( ) {
258
261
list. push( item) ;
259
262
} else {
@@ -272,9 +275,64 @@ impl List {
272
275
}
273
276
}
274
277
275
- Ok ( list )
278
+ Ok ( value! [ void ] )
276
279
} ) ;
277
280
281
+ /** Explicitly extends `extend` to `list`.
282
+
283
+ When `index` is provided, the list behind extend is inserted at the given offset,
284
+ otherwise it is extended to the list's end. */
285
+ tokay_method ! ( "list_extend : @list, extend, index=void" , {
286
+ // Don't extend void
287
+ if extend. is_void( ) {
288
+ return Ok ( value![ void] ) ;
289
+ }
290
+
291
+ // In case extend is not a list, make it a list.
292
+ if !extend. is( "list" ) {
293
+ extend = RefValue :: from( List :: from( extend) ) ;
294
+ }
295
+
296
+ let mut list = list. borrow_mut( ) ;
297
+
298
+ // If first parameter is not a list, just do nothing!
299
+ if let Some ( list) = list. object_mut:: <List >( ) {
300
+ let extend = extend. borrow( ) ;
301
+ let extend = extend. object:: <List >( ) . unwrap( ) ;
302
+
303
+ list. reserve( extend. len( ) ) ;
304
+
305
+ if index. is_void( ) {
306
+ for item in extend. iter( ) {
307
+ if !item. is_void( ) {
308
+ list. push( item. clone( ) ) ;
309
+ }
310
+ }
311
+ } else {
312
+ let mut index = index. to_usize( ) ?;
313
+ let len = list. len( ) ;
314
+
315
+ if index > len {
316
+ return Err ( format!(
317
+ "{} provided index {} out of range in list sized {}" ,
318
+ __function, index, len
319
+ )
320
+ . into( ) ) ;
321
+ }
322
+
323
+ for item in extend. iter( ) {
324
+ if !item. is_void( ) {
325
+ list. insert( index, item. clone( ) ) ;
326
+ index += 1 ;
327
+ }
328
+ }
329
+ }
330
+ }
331
+
332
+ Ok ( value![ void] )
333
+ } ) ;
334
+
335
+ /** Pops item off a list. */
278
336
tokay_method ! ( "list_pop : @list, index=void" , {
279
337
let index = if index. is_void( ) {
280
338
None
@@ -287,39 +345,28 @@ impl List {
287
345
return Ok ( list) ; // "pops" the list, which is not a list
288
346
}
289
347
290
- return Err ( format!(
291
- "{} provided index {} out of range" ,
292
- __function,
293
- index. unwrap( )
294
- )
295
- . into( ) ) ;
348
+ return Ok ( value![ void] ) ;
296
349
}
297
350
298
351
let mut list = list. borrow_mut( ) ;
299
352
let list = list. object_mut:: <List >( ) . unwrap( ) ;
300
353
301
354
// Either pop or remove, regarding index setting.
302
- match index {
355
+ Ok ( match index {
303
356
None => match list. pop( ) {
304
- Some ( item) => Ok ( item) ,
305
- None => {
306
- return Err ( format!( "{} can't pop off empty list" , __function) . into( ) ) ;
307
- }
357
+ Some ( item) => item,
358
+ None => value![ void] ,
308
359
} ,
309
360
Some ( index) => {
310
361
let len = list. len( ) ;
311
362
312
- if index >= len {
313
- return Err ( format!(
314
- "{} provided index {} out of range of list sized {}" ,
315
- __function, index, len
316
- )
317
- . into( ) ) ;
363
+ if index < len {
364
+ list. remove( index)
365
+ } else {
366
+ value![ void]
318
367
}
319
-
320
- Ok ( list. remove( index) )
321
368
}
322
- }
369
+ } )
323
370
} ) ;
324
371
325
372
tokay_method ! ( "list_sort : @list" , {
@@ -379,6 +426,7 @@ impl From<RefValue> for List {
379
426
let list = list. object :: < List > ( ) . unwrap ( ) ;
380
427
( * list) . clone ( )
381
428
}
429
+ "void" => Self { list : Vec :: new ( ) } ,
382
430
_ => Self {
383
431
list : vec ! [ refvalue. clone( ) ] ,
384
432
} ,
0 commit comments