1use crate::{handle::Handle, table::Table, type_kind::TypeKind};
5use cl_ast::{PathPart, Sym, Ty, TyArray, TyFn, TyKind, TyPtr, TyRef, TySlice, TyTuple};
6
7#[derive(Clone, Debug, PartialEq, Eq)] pub enum Error {
9 BadPath { parent: Handle, path: Vec<PathPart> },
10}
11
12impl std::error::Error for Error {}
13impl std::fmt::Display for Error {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 match self {
16 Error::BadPath { parent, path } => {
17 write!(f, "No item at path {parent}")?;
18 for part in path {
19 write!(f, "::{part}")?;
20 }
21 }
22 }
23 Ok(())
24 }
25}
26
27pub trait TypeExpression<Out = Handle> {
30 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Out, Error>;
32}
33
34impl TypeExpression for Ty {
35 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
36 self.kind.evaluate(table, node)
37 }
38}
39
40impl TypeExpression for TyKind {
41 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
42 match self {
43 TyKind::Never => Ok(table.get_lang_item("never")),
44 TyKind::Infer => Ok(table.inferred_type()),
45 TyKind::Path(p) => p.evaluate(table, node),
46 TyKind::Array(a) => a.evaluate(table, node),
47 TyKind::Slice(s) => s.evaluate(table, node),
48 TyKind::Tuple(t) => t.evaluate(table, node),
49 TyKind::Ref(r) => r.evaluate(table, node),
50 TyKind::Ptr(r) => r.evaluate(table, node),
51 TyKind::Fn(f) => f.evaluate(table, node),
52 }
53 }
54}
55
56impl TypeExpression for cl_ast::Path {
57 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
58 let Self { absolute, parts } = self;
59 parts.evaluate(table, if *absolute { table.root() } else { node })
60 }
61}
62
63impl TypeExpression for [PathPart] {
64 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
65 table
66 .nav(node, self)
67 .ok_or_else(|| Error::BadPath { parent: node, path: self.to_owned() })
68 }
69}
70
71impl TypeExpression for Sym {
72 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
73 let path = [PathPart::Ident(*self)];
74 table
75 .nav(node, &path)
76 .ok_or_else(|| Error::BadPath { parent: node, path: path.to_vec() })
77 }
78}
79
80impl TypeExpression for TyArray {
81 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
82 let Self { ty, count } = self;
83 let kind = TypeKind::Array(ty.evaluate(table, node)?, *count);
84 Ok(table.anon_type(kind))
85 }
86}
87
88impl TypeExpression for TySlice {
89 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
90 let Self { ty } = self;
91 let kind = TypeKind::Slice(ty.evaluate(table, node)?);
92 Ok(table.anon_type(kind))
93 }
94}
95
96impl TypeExpression for TyTuple {
97 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
98 let Self { types } = self;
99 let kind = TypeKind::Tuple(types.evaluate(table, node)?);
100 Ok(table.anon_type(kind))
101 }
102}
103
104impl TypeExpression for TyRef {
105 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
106 let Self { mutable: _, count, to } = self;
107 let mut t = to.evaluate(table, node)?;
108 for _ in 0..*count {
109 let kind = TypeKind::Ref(t);
110 t = table.anon_type(kind)
111 }
112 Ok(t)
113 }
114}
115
116impl TypeExpression for TyPtr {
117 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
118 let Self { to } = self;
119 let mut t = to.evaluate(table, node)?;
120 t = table.anon_type(TypeKind::Ptr(t));
121 Ok(t)
122 }
123}
124
125impl TypeExpression for TyFn {
126 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
127 let Self { args, rety } = self;
128 let kind = TypeKind::FnSig {
129 args: args.evaluate(table, node)?,
130 rety: rety.evaluate(table, node)?,
131 };
132 Ok(table.anon_type(kind))
133 }
134}
135
136impl<T: TypeExpression<U>, U> TypeExpression<Vec<U>> for [T] {
137 fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Vec<U>, Error> {
138 let mut out = Vec::with_capacity(self.len());
139 for te in self {
140 out.push(te.evaluate(table, node)?) }
142 Ok(out)
143 }
144}