cl_typeck/
type_expression.rs

1//! A [TypeExpression] is a [syntactic](cl_ast) representation of a [TypeKind], and is used to
2//! construct type bindings in a [Table]'s typing context.
3
4use 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)] // TODO: impl Display and Error
8pub 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
27/// A [TypeExpression] is a syntactic representation of a [TypeKind], and is used to construct
28/// type bindings in a [Table]'s typing context.
29pub trait TypeExpression<Out = Handle> {
30    /// Evaluates a type expression, recursively creating intermediate bindings.
31    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)?) // try_collect is unstable
141        }
142        Ok(out)
143    }
144}