1use std::ops::Range;
7
8use winnow::{
9 LocatingSlice, ModalResult, Parser,
10 ascii::{multispace0, multispace1},
11 combinator::{cut_err, preceded, repeat, seq, terminated},
12 error::{StrContext, StrContextValue},
13};
14
15use crate::{
16 raw_syntax::TermR,
17 text::{HasParser, Name, Span, comment_parser},
18 typecheck::{Env, TypeCheckError},
19 typed_syntax::TermT,
20};
21
22#[derive(Clone, Debug)]
24pub struct Command<S> {
25 pub gates: Vec<(Name, TermR<S>)>,
27 pub term: TermR<S>,
29}
30
31impl<S: Span> Command<S> {
32 pub fn check(&self) -> Result<(Env, TermT), TypeCheckError<S>> {
34 let mut env = Env::default();
35 for (name, tm) in &self.gates {
36 let t = tm.check(&env, None)?;
37 env.0.insert(name.clone(), t);
38 }
39 let tm = self.term.check(&env, None)?;
40 Ok((env, tm))
41 }
42}
43
44impl HasParser for Command<Range<usize>> {
45 fn parser(input: &mut LocatingSlice<&str>) -> ModalResult<Self> {
46 let gate = preceded(
47 "gate",
48 cut_err(seq!(_: multispace1,
49 Name::parser,
50 _: (multispace0, "=", multispace0).context(StrContext::Expected(StrContextValue::CharLiteral('='))),
51 TermR::parser,
52 _: (multispace0, ","))).context(StrContext::Label("gate definition"))
53 );
54
55 comment_parser.parse_next(input)?;
56 let gates = repeat(0.., terminated(gate, comment_parser)).parse_next(input)?;
57 let term = TermR::parser
58 .context(StrContext::Label("Term"))
59 .parse_next(input)?;
60 comment_parser.parse_next(input)?;
61 Ok(Command { gates, term })
62 }
63}