1use anyhow::{Result, anyhow};
2use dynamic::Dynamic;
3use smol_str::SmolStr;
4
5use super::{Parser, Span, Type, expr::Expr};
6
7#[derive(Debug, Clone)]
8pub struct Pattern {
9 pub kind: PatternKind,
10 pub span: Span,
11}
12
13#[derive(Debug, Clone)]
14pub enum PatternKind {
15 Wildcard,
16 Var { idx: u32, ty: Type },
17 Ident { name: SmolStr, ty: Type },
18 Literal(Dynamic),
19 Tuple(Vec<Pattern>),
20 List { elems: Vec<Pattern>, has_rest: bool },
21 Member(Box<Pattern>, SmolStr),
22 Idx(Box<Pattern>, Expr),
23}
24
25impl Pattern {
26 pub fn new(kind: PatternKind, span: Span) -> Self {
27 Self { kind, span }
28 }
29
30 pub fn var(&self) -> Option<u32> {
31 if let PatternKind::Var { idx, .. } = &self.kind { Some(*idx) } else { None }
32 }
33
34 pub fn expr(&self) -> Result<Expr> {
35 if let PatternKind::Var { idx, .. } = &self.kind { Ok(Expr::new(super::expr::ExprKind::Var(*idx), self.span)) } else { Err(anyhow!("不是变量")) }
36 }
37}
38
39impl Parser {
40 pub fn pattern(&mut self) -> Result<Pattern> {
41 self.whitespace()?;
42 let start = self.current_pos();
43 if self.just("_").is_ok() {
44 Ok(Pattern::new(PatternKind::Wildcard, self.span_from(start)))
45 } else if self.just("(").is_ok() {
46 Ok(Pattern::new(PatternKind::Tuple(crate::parse_list!(self, Vec::new(), b')', b',', self.pattern()?)), self.span_from(start)))
47 } else if self.just("[").is_ok() {
48 Ok(Pattern::new(PatternKind::List { elems: crate::parse_list!(self, Vec::new(), b']', b',', self.pattern()?), has_rest: false }, self.span_from(start)))
49 } else if let Ok(text) = self.string() {
50 Ok(Pattern::new(PatternKind::Literal(Dynamic::String(text)), self.span_from(start)))
51 } else if let Ok((name, ty)) = self.ident_typed() {
52 Ok(Pattern::new(PatternKind::Ident { name, ty }, self.span_from(start)))
53 } else {
54 Err(anyhow!("无效的模式 {:?}", String::from_utf8_lossy(&self.buf[self.pos..])))
55 }
56 }
57}