(
&mut self,
expr: Box<Expr<'gc>>,
arms: Vec<MatchArm<'gc>>,
)
| 951 | } |
| 952 | |
| 953 | fn generate_match( |
| 954 | &mut self, |
| 955 | expr: Box<Expr<'gc>>, |
| 956 | arms: Vec<MatchArm<'gc>>, |
| 957 | ) -> Result<(), VmError> { |
| 958 | // Generate the value being matched |
| 959 | self.generate_expr(expr)?; |
| 960 | let expr_slot = self.local_count - 1; |
| 961 | |
| 962 | let mut exit_jumps = Vec::new(); |
| 963 | |
| 964 | self.begin_scope(); |
| 965 | let arm_count = arms.len(); |
| 966 | let mut declared_arm_variable = false; |
| 967 | for (i, arm) in arms.into_iter().enumerate() { |
| 968 | let is_last = i == arm_count - 1; |
| 969 | |
| 970 | // For multiple patterns in an arm, we'll use a series of jumps |
| 971 | let mut pattern_jumps = Vec::new(); |
| 972 | let arm_pattern_count = arm.patterns.len(); |
| 973 | // Generate or-chain of pattern tests |
| 974 | for (j, pattern) in arm.patterns.into_iter().enumerate() { |
| 975 | match pattern { |
| 976 | MatchPattern::EnumVariant { enum_name, variant } => { |
| 977 | // Validate enum and variant exist |
| 978 | if let Some(enum_) = self.get_enum(enum_name.lexeme) { |
| 979 | let variant_name = self.ctx.intern(variant.lexeme.as_bytes()); |
| 980 | if enum_.borrow().get_variant_value(variant_name).is_none() { |
| 981 | self.error_at( |
| 982 | variant, |
| 983 | &format!( |
| 984 | "No variant called '{}' in enum '{}'.", |
| 985 | variant.lexeme, enum_name.lexeme |
| 986 | ), |
| 987 | ); |
| 988 | return Err(VmError::CompileError); |
| 989 | } |
| 990 | } else { |
| 991 | self.error_at( |
| 992 | enum_name, |
| 993 | &format!("Invalid enum '{}'.", enum_name.lexeme), |
| 994 | ); |
| 995 | return Err(VmError::CompileError); |
| 996 | } |
| 997 | |
| 998 | self.named_variable(enum_name, false)?; |
| 999 | let name_constant = self.identifier_constant(variant.lexeme); |
| 1000 | self.emit(OpCode::EnumVariant { |
| 1001 | name_constant: name_constant as u8, |
| 1002 | evaluate: false, |
| 1003 | }); |
| 1004 | self.emit(OpCode::EqualInplace); |
| 1005 | } |
| 1006 | MatchPattern::Literal { value } => { |
| 1007 | self.emit_constant((value).into()); |
| 1008 | self.emit(OpCode::EqualInplace); |
| 1009 | } |
| 1010 | MatchPattern::Variable { name } => { |
no test coverage detected