@@ -102,48 +102,87 @@ impl From<String> for LiteralString {
102
102
pub struct Part {
103
103
source : Box < dyn Stream > ,
104
104
indices : Box < dyn Stream > ,
105
- rest : Vec < Item > ,
105
+ rest : Vec < Expr > ,
106
106
env : Rc < Env >
107
107
}
108
108
109
109
impl Part {
110
110
fn eval ( node : Node , env : & Rc < Env > ) -> Result < Item , StreamError > {
111
- let mut node = node. eval_all ( env) ?;
112
- let source = try_with ! ( node, node. source_checked( ) ?. to_stream( ) ) ;
113
- match node. args . first ( ) {
114
- None => {
115
- Err ( StreamError :: new ( "at least 1 argument required" , node) )
116
- } ,
117
- Some ( first) => {
118
- match first {
119
- Item :: Number ( index) => {
120
- try_with ! ( node, index. check_within( Number :: one( ) ..) ) ;
121
- match source. length ( ) {
122
- Length :: Exact ( len) | Length :: AtMost ( len) if & len < index =>
123
- return Err ( StreamError :: new ( "index past end of stream" , node) ) ,
124
- _ => ( )
125
- }
126
- let mut iter = source. iter ( ) ;
127
- if iter. skip_n ( & ( index - 1 ) ) ?. is_some ( ) {
128
- return Err ( StreamError :: new ( "index past end of stream" , node) ) ;
129
- }
130
- let item = match iter. next ( ) {
131
- Some ( value) => value?,
132
- None => return Err ( StreamError :: new ( "index past end of stream" , node) )
133
- } ;
134
- node. args . remove ( 0 ) ;
135
- if node. args . is_empty ( ) {
136
- Ok ( item)
137
- } else {
138
- Part :: eval ( ENode { head : node. head , source : Some ( item) , args : node. args } . into ( ) , env)
111
+ use once_cell:: unsync:: Lazy ;
112
+ let mut node = node. eval_source ( env) ?;
113
+ let source = try_with ! ( node, node. source_checked( ) ?. as_item( ) ?. to_stream( ) ) ;
114
+ try_with ! ( node, node. check_args_nonempty( ) ) ;
115
+ let length = Lazy :: new ( || match source. length ( ) {
116
+ Length :: Exact ( len) => Ok ( len) ,
117
+ Length :: Infinite => Err ( BaseError :: from ( "stream is infinite" ) ) ,
118
+ _ => Ok ( source. iter ( ) . count ( ) . into ( ) )
119
+ } ) ;
120
+ type R = Result < Number , BaseError > ;
121
+ fn subs_len ( expr : & mut Expr , length : & Lazy < R , impl Fn ( ) -> R > ) ->
122
+ Result < ( ) , BaseError >
123
+ {
124
+ match expr {
125
+ Expr :: Imm ( _) => Ok ( ( ) ) ,
126
+ Expr :: Eval ( node) => {
127
+ if & node. head == "len" && node. source . is_none ( ) {
128
+ match Lazy :: force ( length) {
129
+ Ok ( len) => * expr = Expr :: new_number ( len. to_owned ( ) ) ,
130
+ Err ( err) => return Err ( err. clone ( ) )
139
131
}
140
- } ,
141
- Item :: Stream ( _) => {
142
- let indices = node. args . remove ( 0 ) . to_stream ( ) . unwrap ( ) ;
143
- Ok ( Item :: new_stream ( Part { source, indices, rest : node. args , env : Rc :: clone ( env) } ) )
144
- } ,
145
- _ => Err ( StreamError :: new ( format ! ( "expected number or stream, found {:?}" , first) , node) )
132
+ return Ok ( ( ) ) ;
133
+ }
134
+ node. source . iter_mut ( ) . try_for_each ( |sbox| subs_len ( sbox, length) ) ?;
135
+ match & mut node. head {
136
+ Head :: Lang ( LangItem :: Part ) => return Ok ( ( ) ) , // $part does not enter into args
137
+ Head :: Block ( expr) => subs_len ( expr, length) ?,
138
+ Head :: Lang ( LangItem :: Args ( head) ) => {
139
+ if let Head :: Block ( ref mut expr) = * * head {
140
+ subs_len ( expr, length) ?
141
+ }
142
+ } ,
143
+ _ => ( )
144
+ }
145
+ node. args . iter_mut ( ) . try_for_each ( |arg| subs_len ( arg, length) ) ?;
146
+ Ok ( ( ) )
147
+ }
148
+ }
149
+ }
150
+ try_with ! ( node, subs_len( node. args. get_mut( 0 ) . unwrap( ) , & length) ) ;
151
+ let first = node. args . remove ( 0 ) . eval_env ( env) ?;
152
+ match first {
153
+ Item :: Number ( index) => {
154
+ macro_rules! orig_node {
155
+ ( ) => { {
156
+ node. args. insert( 0 , Expr :: new_number( index) ) ;
157
+ node
158
+ } }
159
+ }
160
+ try_with ! ( orig_node!( ) , index. check_within( Number :: one( ) ..) ) ;
161
+ match source. length ( ) {
162
+ Length :: Exact ( len) | Length :: AtMost ( len) if len < index =>
163
+ return Err ( StreamError :: new ( "index past end of stream" , orig_node ! ( ) ) ) ,
164
+ _ => ( )
165
+ }
166
+ let mut iter = source. iter ( ) ;
167
+ if iter. skip_n ( & ( & index - 1 ) ) ?. is_some ( ) {
168
+ return Err ( StreamError :: new ( "index past end of stream" , orig_node ! ( ) ) ) ;
169
+ }
170
+ let item = match iter. next ( ) {
171
+ Some ( value) => value?,
172
+ None => return Err ( StreamError :: new ( "index past end of stream" , orig_node ! ( ) ) )
173
+ } ;
174
+ if node. args . is_empty ( ) {
175
+ Ok ( item)
176
+ } else {
177
+ Part :: eval ( Node :: new ( node. head , Some ( item. into ( ) ) , node. args ) , env)
146
178
}
179
+ } ,
180
+ Item :: Stream ( indices) => {
181
+ Ok ( Item :: new_stream ( Part { source, indices, rest : node. args , env : Rc :: clone ( env) } ) )
182
+ } ,
183
+ item => {
184
+ node. args . insert ( 0 , item. into ( ) ) ;
185
+ Err ( StreamError :: new ( format ! ( "expected number or stream, found {:?}" , node. args[ 0 ] ) , node) )
147
186
}
148
187
}
149
188
}
@@ -158,8 +197,8 @@ impl Stream for Part {
158
197
impl Describe for Part {
159
198
fn describe ( & self ) -> String {
160
199
let mut args = self . rest . clone ( ) ;
161
- let source = self . source . to_item ( ) ;
162
- args. insert ( 0 , self . indices . to_item ( ) ) ;
200
+ let source = self . source . to_expr ( ) ;
201
+ args. insert ( 0 , self . indices . to_expr ( ) ) ;
163
202
Node :: describe_helper ( & Head :: Lang ( LangItem :: Part ) , Some ( & source) , & args)
164
203
}
165
204
}
@@ -190,9 +229,9 @@ impl Iterator for PartIter<'_> {
190
229
} ;
191
230
// TODO: smarter - number tracks increments, stream unfolds?
192
231
let mut args = self . parent . rest . clone ( ) ;
193
- args. insert ( 0 , part) ;
194
- let node = ENode { head : LangItem :: Part . into ( ) , source : Some ( self . parent . source . to_item ( ) ) , args} ;
195
- Some ( Part :: eval ( node. into ( ) , & self . parent . env ) )
232
+ args. insert ( 0 , Expr :: Imm ( part) ) ;
233
+ let node = Node :: new ( LangItem :: Part , Some ( self . parent . source . to_expr ( ) ) , args) ;
234
+ Some ( Part :: eval ( node, & self . parent . env ) )
196
235
}
197
236
}
198
237
@@ -227,6 +266,18 @@ fn test_part() {
227
266
assert ! ( parse( "seq[2,5]" ) . unwrap( ) . eval( ) . is_err( ) ) ;
228
267
assert_eq ! ( parse( "seq[[2,5]]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[2, 5]" ) ;
229
268
assert_eq ! ( parse( "seq[[[2,5]]]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[[2, 5]]" ) ; // subject to change
269
+
270
+ assert_eq ! ( parse( "[1,2,3][len]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "3" ) ;
271
+ assert_eq ! ( parse( "[1,2,3][[len]]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[3]" ) ;
272
+ assert_eq ! ( parse( "[1,2,3][len-seq]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[2, 1, <!>" ) ;
273
+ assert_eq ! ( parse( "[[1], [1,2,3]][len, len]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "3" ) ;
274
+ assert_eq ! ( parse( "[[1], [1,2,3]][1..2, len]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[1, 3]" ) ;
275
+ assert_eq ! ( parse( "[1,2,3][[1,2].len]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "2" ) ;
276
+ assert ! ( parse( "[1,2,3][seq[len]]" ) . unwrap( ) . eval( ) . is_err( ) ) ;
277
+ assert_eq ! ( parse( "[1,2,3][range(len-1)[len]]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "2" ) ;
278
+ assert_eq ! ( parse( "[1,2,3,4][{#1..(#1+1)}(len/2)]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "[2, 3]" ) ;
279
+ assert_eq ! ( parse( "[1,2,3][{len}]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "3" ) ;
280
+ assert_eq ! ( parse( "[1,2,3][{len}@[]]" ) . unwrap( ) . eval( ) . unwrap( ) . to_string( ) , "3" ) ;
230
281
}
231
282
232
283
0 commit comments