1use crate::{consteval::ConstEval, handle::Handle, table::Table, type_kind::TypeKind};
5use cl_ast::{AstNode, AstTypes, At, Expr, Pat, PatOp, types::Symbol};
6
7#[derive(Clone, Debug, PartialEq, Eq)] pub enum Error {
9 BadPath { parent: Handle, path: Vec<Symbol> },
10 ConstEval { parent: Handle, eval: Box<At<Expr>> },
11}
12
13impl std::error::Error for Error {}
14impl std::fmt::Display for Error {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 Error::BadPath { parent, path } => {
18 write!(f, "No item at path {parent}")?;
19 for part in path {
20 write!(f, "::{part}")?;
21 }
22 }
23 Error::ConstEval { parent, eval } => {
24 write!(f, "Failed to evaluate constant {eval} in {parent}")?;
25 }
26 }
27 Ok(())
28 }
29}
30
31pub trait TypeExpression<Out = Handle> {
34 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Out, Error>;
36}
37
38impl TypeExpression for Pat {
39 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
40 match self {
41 Pat::Ignore => Ok(table.inferred_type()),
42 Pat::Never => Ok(table.get_lang_item("never")),
43 Pat::MetId(_) => todo!(),
44 Pat::Name(name) => name.evaluate(table, node),
45 Pat::Value(expr) => expr.0.evaluate(table, node),
46
47 Pat::Op(PatOp::MetaInner | PatOp::MetaOuter, pats) if let [pat] = &pats[..] => {
48 pat.evaluate(table, node)
49 }
50 Pat::Op(PatOp::Pub, pats) if let [pat] = &pats[..] => pat.evaluate(table, node),
51 Pat::Op(PatOp::Mut, pats) if let [pat] = &pats[..] => pat.evaluate(table, node),
52 Pat::Op(PatOp::Ref, pats) if let [pat] = &pats[..] => {
53 let ty = pat.evaluate(table, node)?;
54 Ok(table.anon_type(TypeKind::Ref(ty)))
55 }
56 Pat::Op(PatOp::Ptr, pats) if let [pat] = &pats[..] => {
57 let ty = pat.evaluate(table, node)?;
58 Ok(table.anon_type(TypeKind::Ptr(ty)))
59 }
60 Pat::Op(PatOp::Guard, pats) if let [pat, _g] = &pats[..] => pat.evaluate(table, node),
61 Pat::Op(PatOp::Rest, _pats) => Ok(table.inferred_type()),
62 Pat::Op(PatOp::RangeEx, _pats) => todo!(),
63 Pat::Op(PatOp::RangeIn, _pats) => todo!(),
64 Pat::Op(PatOp::Record, pats) => {
65 let tys = pats.evaluate(table, node)?;
66 todo!("Anonymous record destructuring {tys:?} in {self}")
67 }
68 Pat::Op(PatOp::Tuple, pats) => {
69 let tys = pats.evaluate(table, node)?;
70 Ok(table.anon_type(TypeKind::Tuple(tys)))
71 }
72 Pat::Op(PatOp::Slice, _) => todo!(""),
73 Pat::Op(PatOp::ArRep, pats) if let [pat, rep] = &pats[..] => {
74 let ty = pat.evaluate(table, node)?;
75 let rep = match rep.value() {
76 Self::Value(at) => at
77 .const_eval()
78 .ok_or_else(|| Error::ConstEval { parent: node, eval: at.clone() }),
79 _ => todo!("{rep} in array-repetition patterns"),
80 }?;
81 Ok(table.anon_type(TypeKind::Array(ty, rep as _)))
82 }
83 Pat::Op(PatOp::Typed, pats) if let [_, pat] = &pats[..] => {
84 Ok(pat.evaluate(table, node)?)
85 }
86 Pat::Op(PatOp::TypePrefixed, pats) => todo!("TypePrefixed {pats:?}"),
87 Pat::Op(PatOp::Generic, pats) if let [pat, ..] = &pats[..] => {
88 Ok(pat.evaluate(table, node)?)
89 }
90 Pat::Op(PatOp::Fn, pats) => todo!("Fn {pats:?}"),
91 Pat::Op(PatOp::Alt, pats) => todo!("Alt {pats:?}"),
92 _ => unreachable!(),
93 }
94 }
95}
96
97impl TypeExpression for cl_ast::Expr {
98 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
99 match self {
100 Self::Omitted => Ok(table.anon_type(TypeKind::Tuple(vec![]))),
101 Self::Id(path) => path.evaluate(table, node),
102 Self::MetId(_) => todo!("Metaidentifiers in resolver"),
103 Self::Lit(lit) => todo!("Literals ({lit}) in type expressions!"),
104 Self::Use(item) => todo!("Use-items ({item}) in type expressions!??!"),
105 Self::Bind(bind) => todo!("Bind-items ({bind}) in type expressions!"),
106 Self::Make(make) => todo!("Make-items ({make}) in type expressions!"),
107 Self::Match(mtch) => todo!("Match-exprs ({mtch}) in type expressions!"),
108 Self::Op(op, ats) => todo!("Op({op}, {ats:?})"),
109 }
110 }
111}
112
113impl TypeExpression for cl_ast::types::Path {
114 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
115 let Self { parts } = self;
116 parts.evaluate(table, node)
117 }
118}
119
120impl TypeExpression for [Symbol] {
121 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
122 table
123 .nav(node, self)
124 .ok_or_else(|| Error::BadPath { parent: node, path: self.to_owned() })
125 }
126}
127
128impl TypeExpression for Symbol {
129 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
130 let path = [*self];
131 table
132 .nav(node, &path)
133 .ok_or_else(|| Error::BadPath { parent: node, path: path.to_vec() })
134 }
135}
136
137impl<T: TypeExpression<U>, U> TypeExpression<Vec<U>> for [T] {
138 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Vec<U>, Error> {
139 let mut out = Vec::with_capacity(self.len());
140 for te in self {
141 out.push(te.evaluate(table, node)?) }
143 Ok(out)
144 }
145}
146
147impl<T: TypeExpression<U> + AstNode, U, A: AstTypes> TypeExpression<U> for At<T, A> {
148 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<U, Error> {
149 self.0.evaluate(table, node)
150 }
151}