(
&mut self,
p: &ast::PatternMatchMapping,
pc: &mut PatternContext,
)
| 6333 | } |
| 6334 | |
| 6335 | fn compile_pattern_mapping( |
| 6336 | &mut self, |
| 6337 | p: &ast::PatternMatchMapping, |
| 6338 | pc: &mut PatternContext, |
| 6339 | ) -> CompileResult<()> { |
| 6340 | let mapping = p; |
| 6341 | let keys = &mapping.keys; |
| 6342 | let patterns = &mapping.patterns; |
| 6343 | let size = keys.len(); |
| 6344 | let star_target = &mapping.rest; |
| 6345 | |
| 6346 | // Validate pattern count matches key count |
| 6347 | if keys.len() != patterns.len() { |
| 6348 | return Err(self.error(CodegenErrorType::SyntaxError(format!( |
| 6349 | "keys ({}) / patterns ({}) length mismatch in mapping pattern", |
| 6350 | keys.len(), |
| 6351 | patterns.len() |
| 6352 | )))); |
| 6353 | } |
| 6354 | |
| 6355 | // Validate rest pattern: '_' cannot be used as a rest target |
| 6356 | if let Some(rest) = star_target |
| 6357 | && rest.as_str() == "_" |
| 6358 | { |
| 6359 | return Err(self.error(CodegenErrorType::SyntaxError("invalid syntax".to_string()))); |
| 6360 | } |
| 6361 | |
| 6362 | // Step 1: Check if subject is a mapping |
| 6363 | // Stack: [subject] |
| 6364 | pc.on_top += 1; |
| 6365 | |
| 6366 | emit!(self, Instruction::MatchMapping); |
| 6367 | // Stack: [subject, is_mapping] |
| 6368 | |
| 6369 | self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; |
| 6370 | // Stack: [subject] |
| 6371 | |
| 6372 | // Special case: empty pattern {} with no rest |
| 6373 | if size == 0 && star_target.is_none() { |
| 6374 | // If the pattern is just "{}", we're done! Pop the subject |
| 6375 | pc.on_top -= 1; |
| 6376 | emit!(self, Instruction::PopTop); |
| 6377 | return Ok(()); |
| 6378 | } |
| 6379 | |
| 6380 | // Length check for patterns with keys |
| 6381 | if size > 0 { |
| 6382 | // Check if the mapping has at least 'size' keys |
| 6383 | emit!(self, Instruction::GetLen); |
| 6384 | self.emit_load_const(ConstantData::Integer { value: size.into() }); |
| 6385 | // Stack: [subject, len, size] |
| 6386 | emit!( |
| 6387 | self, |
| 6388 | Instruction::CompareOp { |
| 6389 | opname: ComparisonOperator::GreaterOrEqual |
| 6390 | } |
| 6391 | ); |
| 6392 | self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; |
no test coverage detected