1
- #![ allow( clippy:: borrowed_box) ]
1
+ #![ allow( clippy:: redundant_closure_call , clippy :: borrowed_box) ]
2
2
use std:: fmt:: { Display , Formatter , Debug } ;
3
3
use dyn_clone:: DynClone ;
4
4
pub use num:: * ;
@@ -228,9 +228,10 @@ impl Node {
228
228
Ok ( func) => func ( self , env) ,
229
229
Err ( e) => Err ( StreamError :: new ( e, self ) )
230
230
} ,
231
+ Head :: Lang ( ref lang) => find_keyword ( lang. keyword ( ) ) . unwrap ( ) ( self , env) ,
231
232
Head :: Block ( blk) => ( * blk) . apply ( & self . source , & self . args ) ?. eval_env ( env) ,
232
- Head :: Repl ( _ , _ ) => Err ( StreamError :: new ( "out of context" , self ) ) ,
233
- Head :: Lang ( ref lang ) => find_keyword ( lang . keyword ( ) ) . unwrap ( ) ( self , env )
233
+ Head :: Args ( _ ) => Node :: eval_at ( self , env ) ,
234
+ Head :: Repl ( _ , _ ) => Err ( StreamError :: new ( "out of context" , self ) )
234
235
}
235
236
}
236
237
@@ -259,6 +260,24 @@ impl Node {
259
260
Ok(self)
260
261
}*/
261
262
263
+ fn eval_at ( node : Node , env : & Rc < Env > ) -> Result < Item , StreamError > {
264
+ let node = node. eval_all ( env) ?;
265
+ assert ! ( node. args. len( ) == 1 ) ;
266
+ let src_stream = try_with ! ( node, node. args[ 0 ] . as_stream( ) ) ;
267
+ if src_stream. length ( ) == Length :: Infinite {
268
+ return Err ( StreamError :: new ( "stream is infinite" , node) ) ;
269
+ }
270
+ let Head :: Args ( head) = node. head else { unreachable ! ( ) } ;
271
+ let expr = Expr :: Eval ( Node {
272
+ head : * head,
273
+ source : node. source . map ( |item| Box :: new ( item. into ( ) ) ) ,
274
+ args : src_stream. iter ( )
275
+ . map ( |res| res. map ( Expr :: from) )
276
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?
277
+ } ) ;
278
+ expr. eval_env ( env)
279
+ }
280
+
262
281
pub ( crate ) fn apply ( self , source : & Option < Box < Expr > > , args : & Vec < Expr > ) -> Result < Node , StreamError > {
263
282
Ok ( Node {
264
283
head : self . head ,
@@ -418,6 +437,7 @@ pub enum Head {
418
437
Symbol ( String ) ,
419
438
Oper ( String ) ,
420
439
Block ( Box < Expr > ) ,
440
+ Args ( Box < Head > ) , /// At-sign (source.head@args)
421
441
Lang ( LangItem ) ,
422
442
Repl ( char , Option < usize > )
423
443
}
@@ -431,13 +451,13 @@ impl Head {
431
451
Head :: Oper ( _) => Default :: default ( ) ,
432
452
Head :: Repl ( chr, None ) => chr. to_string ( ) ,
433
453
Head :: Repl ( chr, Some ( num) ) => format ! ( "{chr}{num}" ) ,
434
- Head :: Lang ( LangItem :: Args ( head) ) => format ! ( "{}@" , head. describe( ) ) ,
454
+ Head :: Args ( head) => format ! ( "{}@" , head. describe( ) ) ,
435
455
Head :: Lang ( _) => Default :: default ( ) ,
436
456
}
437
457
}
438
458
439
- pub fn args < T > ( head : T ) -> Head where T : Into < Head > {
440
- Head :: Lang ( LangItem :: Args ( Box :: new ( head. into ( ) ) ) )
459
+ pub fn args ( head : impl Into < Head > ) -> Head {
460
+ Head :: Args ( Box :: new ( head. into ( ) ) )
441
461
}
442
462
}
443
463
@@ -490,8 +510,6 @@ pub enum LangItem {
490
510
Part ,
491
511
/// Colon (`source:func` ~ `source.$map(func)`)
492
512
Map ,
493
- /// At-sign (`source.head@args` ~ `source.$args{head}(args)`)
494
- Args ( Box < Head > )
495
513
}
496
514
497
515
impl LangItem {
@@ -500,8 +518,7 @@ impl LangItem {
500
518
match self {
501
519
List => "$list" ,
502
520
Part => "$part" ,
503
- Map => "$map" ,
504
- Args ( _) => "$args"
521
+ Map => "$map"
505
522
}
506
523
}
507
524
}
@@ -1145,6 +1162,18 @@ fn test_block() {
1145
1162
assert_eq ! ( parse( "{#1}({#2}(3,4),5)" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "4" ) ;
1146
1163
}
1147
1164
1165
+ #[ test]
1166
+ fn test_args ( ) {
1167
+ use crate :: parser:: parse;
1168
+ assert_eq ! ( parse( "range@[3]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[1, 2, 3]" ) ;
1169
+ assert_eq ! ( parse( "range@range(3)" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[1]" ) ;
1170
+ assert_eq ! ( parse( "range@range(3)" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[1]" ) ;
1171
+ assert_eq ! ( parse( "range@[3][2]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "2" ) ;
1172
+ assert_eq ! ( parse( "range@range(3)[1]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "1" ) ;
1173
+ assert ! ( parse( "range@3" ) . unwrap( ) . eval( ) . is_err( ) ) ;
1174
+ assert ! ( parse( "range@seq" ) . unwrap( ) . eval( ) . is_err( ) ) ;
1175
+ }
1176
+
1148
1177
#[ test]
1149
1178
fn test_describe ( ) {
1150
1179
use crate :: parser:: parse;
0 commit comments