phase_rs/raw_syntax/
pattern.rs1use std::ops::Range;
4
5use pretty::RcDoc;
6use winnow::{
7 LocatingSlice, ModalResult, Parser,
8 ascii::multispace0,
9 combinator::{alt, delimited, separated},
10};
11
12use crate::{
13 ket::CompKetState,
14 raw_syntax::TermR,
15 text::{HasParser, Span, Spanned, ToDoc},
16 typecheck::{Env, TypeCheckError},
17 typed_syntax::PatternT,
18};
19
20pub type PatternR<S> = Spanned<S, PatternRInner<S>>;
23
24#[derive(Clone, Debug, PartialEq)]
27pub struct PatternRInner<S> {
28 pub(crate) patterns: Vec<PatTensorR<S>>,
29}
30
31impl<S> ToDoc for PatternRInner<S> {
32 fn to_doc(&self) -> RcDoc<'_> {
33 RcDoc::intersperse(
34 self.patterns.iter().map(PatTensorR::to_doc),
35 RcDoc::line().append(". "),
36 )
37 .group()
38 }
39}
40
41pub type PatTensorR<S> = Spanned<S, PatTensorRInner<S>>;
44
45#[derive(Clone, Debug, PartialEq)]
48pub struct PatTensorRInner<S> {
49 pub(crate) patterns: Vec<PatAtomR<S>>,
50}
51
52impl<S> ToDoc for PatTensorRInner<S> {
53 fn to_doc(&self) -> RcDoc<'_> {
54 RcDoc::intersperse(
55 self.patterns.iter().map(PatAtomR::to_doc),
56 RcDoc::line().append("x "),
57 )
58 .group()
59 }
60}
61
62pub type PatAtomR<S> = Spanned<S, PatAtomRInner<S>>;
65
66#[derive(Clone, Debug, PartialEq)]
69pub enum PatAtomRInner<S> {
70 Brackets(PatternR<S>),
72 Ket(CompKetState),
74 Unitary(Box<TermR<S>>),
76}
77
78impl<S> ToDoc for PatAtomRInner<S> {
79 fn to_doc(&self) -> RcDoc<'_> {
80 match self {
81 PatAtomRInner::Brackets(pattern) => RcDoc::text("(")
82 .append(RcDoc::line().append(pattern.to_doc()).nest(2))
83 .append(RcDoc::line())
84 .append(")")
85 .group(),
86 PatAtomRInner::Ket(states) => states.to_doc(),
87 PatAtomRInner::Unitary(inner) => inner.to_doc(),
88 }
89 }
90}
91
92impl<S: Span> PatternR<S> {
93 pub fn check(&self, env: &Env) -> Result<PatternT, TypeCheckError<S>> {
95 let mut pattern_iter = self.inner.patterns.iter();
96 let mut raw = pattern_iter.next().unwrap();
97 let p = raw.check(env)?;
98 let mut ty1 = p.get_type();
99 let mut v = vec![p];
100 for r in pattern_iter {
101 let pattern = r.check(env)?;
102 let ty2 = pattern.get_type();
103 if ty1.1 != ty2.0 {
104 return Err(TypeCheckError::PatternTypeMismatch {
105 p1: raw.clone(),
106 ty1,
107 p2: r.clone(),
108 ty2,
109 });
110 }
111 raw = r;
112 ty1 = ty2;
113 v.push(pattern);
114 }
115 Ok(PatternT::Comp(v))
116 }
117}
118
119impl<S: Span> PatTensorR<S> {
120 fn check(&self, env: &Env) -> Result<PatternT, TypeCheckError<S>> {
121 Ok(PatternT::Tensor(
122 self.inner
123 .patterns
124 .iter()
125 .map(|p| p.check(env))
126 .collect::<Result<_, _>>()?,
127 ))
128 }
129}
130
131impl<S: Span> PatAtomR<S> {
132 fn check(&self, env: &Env) -> Result<PatternT, TypeCheckError<S>> {
133 match &self.inner {
134 PatAtomRInner::Brackets(pattern) => pattern.check(env),
135 PatAtomRInner::Ket(states) => Ok(PatternT::Ket(states.clone())),
136 PatAtomRInner::Unitary(inner) => {
137 Ok(PatternT::Unitary(Box::new(inner.check(env, None)?)))
138 }
139 }
140 }
141}
142
143impl HasParser for PatternRInner<Range<usize>> {
144 fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
145 separated(1.., PatTensorR::parser, (multispace0, '.', multispace0))
146 .map(|patterns| PatternRInner { patterns })
147 .parse_next(input)
148 }
149}
150
151impl HasParser for PatTensorRInner<Range<usize>> {
152 fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
153 separated(1.., PatAtomR::parser, (multispace0, 'x', multispace0))
154 .map(|patterns| PatTensorRInner { patterns })
155 .parse_next(input)
156 }
157}
158
159impl HasParser for PatAtomRInner<Range<usize>> {
160 fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
161 alt((
162 delimited(("(", multispace0), PatternR::parser, (multispace0, ")"))
163 .map(PatAtomRInner::Brackets),
164 CompKetState::parser.map(PatAtomRInner::Ket),
165 TermR::parser.map(|x| PatAtomRInner::Unitary(Box::new(x))),
166 ))
167 .parse_next(input)
168 }
169}