1- #![ allow( clippy:: borrowed_box) ]
1+ #![ allow( clippy:: redundant_closure_call , clippy :: borrowed_box) ]
22use std:: fmt:: { Display , Formatter , Debug } ;
33use dyn_clone:: DynClone ;
44pub use num:: * ;
@@ -228,9 +228,10 @@ impl Node {
228228 Ok ( func) => func ( self , env) ,
229229 Err ( e) => Err ( StreamError :: new ( e, self ) )
230230 } ,
231+ Head :: Lang ( ref lang) => find_keyword ( lang. keyword ( ) ) . unwrap ( ) ( self , env) ,
231232 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 ) )
234235 }
235236 }
236237
@@ -259,6 +260,24 @@ impl Node {
259260 Ok(self)
260261 }*/
261262
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+
262281 pub ( crate ) fn apply ( self , source : & Option < Box < Expr > > , args : & Vec < Expr > ) -> Result < Node , StreamError > {
263282 Ok ( Node {
264283 head : self . head ,
@@ -418,6 +437,7 @@ pub enum Head {
418437 Symbol ( String ) ,
419438 Oper ( String ) ,
420439 Block ( Box < Expr > ) ,
440+ Args ( Box < Head > ) , /// At-sign (source.head@args)
421441 Lang ( LangItem ) ,
422442 Repl ( char , Option < usize > )
423443}
@@ -431,13 +451,13 @@ impl Head {
431451 Head :: Oper ( _) => Default :: default ( ) ,
432452 Head :: Repl ( chr, None ) => chr. to_string ( ) ,
433453 Head :: Repl ( chr, Some ( num) ) => format ! ( "{chr}{num}" ) ,
434- Head :: Lang ( LangItem :: Args ( head) ) => format ! ( "{}@" , head. describe( ) ) ,
454+ Head :: Args ( head) => format ! ( "{}@" , head. describe( ) ) ,
435455 Head :: Lang ( _) => Default :: default ( ) ,
436456 }
437457 }
438458
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 ( ) ) )
441461 }
442462}
443463
@@ -490,8 +510,6 @@ pub enum LangItem {
490510 Part ,
491511 /// Colon (`source:func` ~ `source.$map(func)`)
492512 Map ,
493- /// At-sign (`source.head@args` ~ `source.$args{head}(args)`)
494- Args ( Box < Head > )
495513}
496514
497515impl LangItem {
@@ -500,8 +518,7 @@ impl LangItem {
500518 match self {
501519 List => "$list" ,
502520 Part => "$part" ,
503- Map => "$map" ,
504- Args ( _) => "$args"
521+ Map => "$map"
505522 }
506523 }
507524}
@@ -1145,6 +1162,18 @@ fn test_block() {
11451162 assert_eq ! ( parse( "{#1}({#2}(3,4),5)" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "4" ) ;
11461163}
11471164
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+
11481177#[ test]
11491178fn test_describe ( ) {
11501179 use crate :: parser:: parse;
0 commit comments