(&mut self, _can_assign: bool)
| 1972 | } |
| 1973 | |
| 1974 | fn match_expression(&mut self, _can_assign: bool) -> Option<Expr<'gc>> { |
| 1975 | let line = self.previous.line; |
| 1976 | self.stop_at_brace = true; |
| 1977 | let expr = Box::new(self.expression()?); |
| 1978 | self.stop_at_brace = false; |
| 1979 | |
| 1980 | self.consume(TokenType::OpenBrace, "Expect '{' after match expression."); |
| 1981 | |
| 1982 | if self.check(TokenType::CloseBrace) { |
| 1983 | self.error_at_current( |
| 1984 | "Empty match not allowed. A match expression must have at least one arm.", |
| 1985 | ); |
| 1986 | return None; |
| 1987 | } |
| 1988 | |
| 1989 | let mut arms: Vec<MatchArm> = Vec::new(); |
| 1990 | let mut seen_patterns = HashSet::new(); |
| 1991 | let mut has_wildcard = false; |
| 1992 | |
| 1993 | // Set mode for parsing match arms |
| 1994 | self.in_match_arm = true; |
| 1995 | while !self.check(TokenType::CloseBrace) && !self.is_at_end() { |
| 1996 | let arm = self.match_arm()?; |
| 1997 | |
| 1998 | for pattern in &arm.patterns { |
| 1999 | match pattern { |
| 2000 | MatchPattern::Wildcard => { |
| 2001 | if has_wildcard { |
| 2002 | self.error("Multiple wildcard patterns in match expression."); |
| 2003 | } |
| 2004 | has_wildcard = true; |
| 2005 | } |
| 2006 | MatchPattern::EnumVariant { enum_name, variant } => { |
| 2007 | let pattern_key = format!("{}::{}", enum_name.lexeme, variant.lexeme); |
| 2008 | if !seen_patterns.insert(pattern_key) { |
| 2009 | self.error_at(*variant, "Duplicate match pattern."); |
| 2010 | } |
| 2011 | } |
| 2012 | MatchPattern::Literal { value } => { |
| 2013 | if !seen_patterns.insert(format!("{:?}", value)) { |
| 2014 | self.error("Duplicate match pattern."); |
| 2015 | } |
| 2016 | } |
| 2017 | MatchPattern::Variable { name } => { |
| 2018 | // FIXME: incorrect duplicate pattern checking due guard hash |
| 2019 | if !seen_patterns.insert(format!("{} {:?}", name.lexeme, arm.guard)) { |
| 2020 | self.error("Duplicate match pattern."); |
| 2021 | } |
| 2022 | } |
| 2023 | MatchPattern::Range { .. } => { |
| 2024 | // Range patterns are validated during parsing |
| 2025 | } |
| 2026 | } |
| 2027 | } |
| 2028 | arms.push(arm); |
| 2029 | } |
| 2030 | self.in_match_arm = false; |
| 2031 |
nothing calls this directly
no test coverage detected