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, Ty, TyArray, TyFn, TyKind, 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.anon_type(TypeKind::Never)),
44            TyKind::Empty => Ok(table.anon_type(TypeKind::Empty)),
45            TyKind::Infer => Ok(table.inferred_type()),
46            TyKind::Path(p) => p.evaluate(table, node),
47            TyKind::Array(a) => a.evaluate(table, node),
48            TyKind::Slice(s) => s.evaluate(table, node),
49            TyKind::Tuple(t) => t.evaluate(table, node),
50            TyKind::Ref(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 TyArray {
72    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
73        let Self { ty, count } = self;
74        let kind = TypeKind::Array(ty.evaluate(table, node)?, *count);
75        Ok(table.anon_type(kind))
76    }
77}
78
79impl TypeExpression for TySlice {
80    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
81        let Self { ty } = self;
82        let kind = TypeKind::Slice(ty.evaluate(table, node)?);
83        Ok(table.anon_type(kind))
84    }
85}
86
87impl TypeExpression for TyTuple {
88    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
89        let Self { types } = self;
90        let kind = match types.len() {
91            0 => TypeKind::Empty,
92            _ => TypeKind::Tuple(types.evaluate(table, node)?),
93        };
94        Ok(table.anon_type(kind))
95    }
96}
97
98impl TypeExpression for TyRef {
99    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
100        let Self { mutable: _, count, to } = self;
101        let mut t = to.evaluate(table, node)?;
102        for _ in 0..*count {
103            let kind = TypeKind::Ref(t);
104            t = table.anon_type(kind)
105        }
106        Ok(t)
107    }
108}
109
110impl TypeExpression for TyFn {
111    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
112        let Self { args, rety } = self;
113        let kind = TypeKind::FnSig {
114            args: args.evaluate(table, node)?,
115            rety: match rety {
116                Some(ty) => ty.evaluate(table, node)?,
117                None => TyKind::Empty.evaluate(table, node)?,
118            },
119        };
120        Ok(table.anon_type(kind))
121    }
122}
123
124impl<T: TypeExpression<U>, U> TypeExpression<Vec<U>> for [T] {
125    fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Vec<U>, Error> {
126        let mut out = Vec::with_capacity(self.len());
127        for te in self {
128            out.push(te.evaluate(table, node)?) // try_collect is unstable
129        }
130        Ok(out)
131    }
132}