Postfix trailers: `.attr`, [i], [s:e], (args), chained. A trailer must start on the same line, so a statement boundary ends the chain (else `x = []` ⏎ `[i]` parses as `[][i]`). */
(&mut self)
| 348 | |
| 349 | /* Postfix trailers: `.attr`, [i], [s:e], (args), chained. A trailer must start on the same line, so a statement boundary ends the chain (else `x = []` ⏎ `[i]` parses as `[][i]`). */ |
| 350 | pub(super) fn postfix_tail(&mut self) { |
| 351 | loop { |
| 352 | match self.peek_same_line() { |
| 353 | Some(TokenType::Lsqb) => { |
| 354 | self.advance(); |
| 355 | self.parse_subscript(); |
| 356 | // Subscript assignment: StoreItem; for slices runtime replaces the range. |
| 357 | if matches!(self.peek(), Some(TokenType::Equal)) { |
| 358 | self.advance(); |
| 359 | self.expr(); |
| 360 | self.chunk.emit(OpCode::StoreItem, 0); |
| 361 | self.chunk.emit(OpCode::LoadNone, 0); |
| 362 | return; |
| 363 | } |
| 364 | self.chunk.emit(OpCode::GetItem, 0); |
| 365 | } |
| 366 | Some(TokenType::Dot) => { |
| 367 | self.advance(); |
| 368 | let t = self.advance(); |
| 369 | let (start, end) = (t.start, t.end); |
| 370 | let idx = self.chunk.push_name(&self.source[start..end]); |
| 371 | // LoadAttr adjacent to Call lets `fuse_method_calls` collapse them. |
| 372 | self.chunk.emit(OpCode::LoadAttr, idx); |
| 373 | } |
| 374 | Some(TokenType::Lpar) => { |
| 375 | // Call after any trailer. |
| 376 | let call_pos = self.last_end as u32; |
| 377 | let (pos, kw) = self.parse_args(); |
| 378 | self.chunk.emit(OpCode::Call, super::pack_call(pos, kw)); |
| 379 | self.chunk.record_call_pos(call_pos); |
| 380 | } |
| 381 | _ => break |
| 382 | } |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | /* lambda: fresh chunk, compiles body to Return, emits MakeFunction. */ |
| 387 | pub(super) fn parse_lambda(&mut self) { |
no test coverage detected