1use crate::parse::term::{AppH, Atom};
4use crate::parse::{self, Symb};
5use crate::{Comb, LTerm, Symbol, Symbols};
6use alloc::string::{String, ToString};
7use alloc::vec::Vec;
8use core::borrow::Borrow;
9
10type Result<T> = core::result::Result<T, Error>;
11
12type PTerm<S> = parse::Term<Atom<Symb<S>>, S>;
13
14pub type Command<'s> = crate::Command<String, Intro<'s>, Rule<'s>>;
15
16pub type Intro<'s> = crate::Intro<LTerm<'s>>;
18
19pub type Rule<'s> = crate::Rule<(String, Option<LTerm<'s>>), TopPattern<'s>, LTerm<'s>>;
23
24pub type TopPattern<'s> = crate::pattern::TopPattern<Symbol<'s>>;
26
27pub type Pattern<'s> = crate::Pattern<Symbol<'s>>;
29
30pub trait Share<'s, Target> {
31 fn share(self, syms: &Symbols<'s>) -> Result<Target>;
32}
33
34#[derive(Debug, Eq, PartialEq)]
35pub enum Error {
36 UndeclaredSymbol(String),
37 NoPrepattern,
38 NoTopPattern,
39}
40
41impl<'s, S: Borrow<str> + Ord> Share<'s, Symbol<'s>> for Symb<S> {
42 fn share(self, syms: &Symbols<'s>) -> Result<Symbol<'s>> {
43 syms.get(&self.path, &self.name)
44 .ok_or_else(|| self.map(|s| s.borrow().to_string()).to_string())
45 .map_err(Error::UndeclaredSymbol)
46 }
47}
48
49impl<'s, R: Borrow<str> + Ord> Share<'s, LTerm<'s>> for AppH<Atom<Symb<R>>, R> {
50 fn share(self, syms: &Symbols<'s>) -> Result<LTerm<'s>> {
51 match self {
52 Self::Atom(Atom::Const(symb)) => Ok(LTerm::Const(symb.share(syms)?)),
53 Self::Atom(Atom::Var(v)) => Ok(LTerm::Var(v)),
54 Self::Atom(Atom::Type) => Ok(LTerm::Type),
55 Self::Prod(x, ty, tm) => {
56 let id = x
57 .map(|x| x.borrow().to_string())
58 .unwrap_or_else(|| "$".to_string());
59 let ty = ty.share(syms)?;
60 Ok(LTerm::Comb(Comb::Prod(id, ty, tm.share(syms)?).into()))
61 }
62 Self::Abst(x, ty, tm) => {
63 let id = x.borrow().to_string();
64 let ty = ty.map(|ty| (*ty).share(syms)).transpose()?;
65 Ok(LTerm::Comb(Comb::Abst(id, ty, tm.share(syms)?).into()))
66 }
67 }
68 }
69}
70
71impl<'s, R: Borrow<str> + Ord> Share<'s, LTerm<'s>> for PTerm<R> {
72 fn share(self, syms: &Symbols<'s>) -> Result<LTerm<'s>> {
73 let head = self.head.share(syms)?;
74 if self.args.is_empty() {
75 Ok(head)
76 } else {
77 let tail: Result<_> = self.args.into_iter().map(|tm| tm.share(syms)).collect();
78 Ok(LTerm::Comb(Comb::Appl(head, tail?).into()))
79 }
80 }
81}
82
83impl<'s> TryFrom<LTerm<'s>> for Pattern<'s> {
84 type Error = Error;
85
86 fn try_from(tm: LTerm<'s>) -> Result<Self> {
87 match tm {
88 LTerm::Const(c) => Ok(Self::Symb(c, Vec::new())),
89 LTerm::Var(v) => Ok(Self::MVar(v)),
90 LTerm::Comb(comb) => match *comb {
91 Comb::Appl(head, args2) => match Self::try_from(head)? {
92 Self::Symb(s, mut args) => {
93 let args2 = args2.into_iter().map(Self::try_from);
94 args.append(&mut args2.collect::<Result<_>>()?);
95 Ok(Self::Symb(s, args))
96 }
97 _ => Err(Error::NoPrepattern),
99 },
100 _ => Err(Error::NoPrepattern),
101 },
102 _ => Err(Error::NoPrepattern),
103 }
104 }
105}
106
107impl<'s, R: Borrow<str> + Ord> Share<'s, Rule<'s>> for parse::Rule<R, PTerm<R>> {
108 fn share(self, syms: &Symbols<'s>) -> Result<Rule<'s>> {
109 let joker = self.ctx.len();
110 let ctx = self.ctx.into_iter().map(|(id, ty)| {
111 let id = id.borrow().to_string();
112 let ty = ty.map(|ty| ty.share(syms)).transpose()?;
113 Ok((id, ty))
114 });
115 let ctx = ctx.collect::<Result<_>>()?;
116
117 let lhs = self.lhs.share(syms)?;
118 let lhs = Pattern::try_from(lhs)?;
119 let lhs = lhs.joke(joker);
120 let lhs = TopPattern::try_from(lhs).map_err(|_| Error::NoTopPattern)?;
121
122 let rhs = self.rhs.share(syms)?;
123
124 Ok(Rule { ctx, lhs, rhs })
125 }
126}
127
128impl<'s, Tm: Share<'s, LTerm<'s>>> Share<'s, Intro<'s>> for parse::Intro<Tm> {
129 fn share(self, syms: &Symbols<'s>) -> Result<Intro<'s>> {
130 match self {
131 Self::Definition(ty, tm) => Ok(Intro::Definition(
132 ty.map(|ty| ty.share(syms)).transpose()?,
133 tm.map(|tm| tm.share(syms)).transpose()?,
134 )),
135 Self::Theorem(ty, tm) => Ok(Intro::Theorem(ty.share(syms)?, tm.share(syms)?)),
136 Self::Declaration(ty) => Ok(Intro::Declaration(ty.share(syms)?)),
137 }
138 }
139}
140
141impl<'s, R: Borrow<str> + Ord> Share<'s, Command<'s>> for parse::Command<R, R, PTerm<R>> {
142 fn share(self, syms: &Symbols<'s>) -> Result<Command<'s>> {
143 match self {
144 Self::Intro(id, args, it) => {
145 let mut args = args.into_iter().rev();
146 let it = args.try_fold(it.share(syms)?, |it, (name, aty)| {
147 let id = name.borrow().to_string();
148 let aty = aty.share(syms)?;
149 Ok(it
150 .map_type(|ty| LTerm::Comb(Comb::Prod(id.clone(), aty.clone(), ty).into()))
151 .map_term(|tm| LTerm::Comb(Comb::Abst(id.clone(), Some(aty), tm).into())))
152 })?;
153 Ok(Command::Intro(id.borrow().to_string(), it))
154 }
155 Self::Rules(rules) => {
156 let rules: Result<_> = rules.into_iter().map(|r| r.share(syms)).collect();
157 Ok(Command::Rules(rules?))
158 }
159 }
160 }
161}