cl_typeck/
entry.rs

1//! An [Entry] is an accessor for [nodes](Handle) in a [Table].
2//!
3//! There are two kinds of entry:
4//! - [Entry]: Provides getters for an entry's fields, and an implementation of
5//!   [Display](std::fmt::Display)
6//! - [EntryMut]: Provides setters for an entry's fields, and an [`as_ref`](EntryMut::as_ref) method
7//!   to demote to an [Entry].
8
9use std::collections::HashMap;
10
11use cl_ast::{Expr, Meta, PathPart, Sym};
12use cl_structures::span::Span;
13
14use crate::{
15    handle::Handle,
16    source::Source,
17    stage::categorize as cat,
18    table::{NodeKind, Table},
19    type_expression::{self as tex, TypeExpression},
20    type_kind::TypeKind,
21};
22
23mod debug;
24mod display;
25
26impl Handle {
27    pub const fn to_entry<'t, 'a>(self, table: &'t Table<'a>) -> Entry<'t, 'a> {
28        Entry { id: self, table }
29    }
30    pub fn to_entry_mut<'t, 'a>(self, table: &'t mut Table<'a>) -> EntryMut<'t, 'a> {
31        EntryMut { id: self, table }
32    }
33}
34
35pub struct Entry<'t, 'a> {
36    table: &'t Table<'a>,
37    id: Handle,
38}
39
40macro_rules! impl_entry_ {
41    () => {
42        pub const fn id(&self) -> Handle {
43            self.id
44        }
45
46        pub const fn inner(&'t self) -> &'t Table<'a> {
47            self.table
48        }
49
50        pub fn kind(&self) -> Option<&NodeKind> {
51            self.table.kind(self.id)
52        }
53
54        pub const fn root(&self) -> Handle {
55            self.table.root()
56        }
57
58        pub fn children(&self) -> Option<&HashMap<Sym, Handle>> {
59            self.table.children(self.id)
60        }
61
62        pub fn imports(&self) -> Option<&HashMap<Sym, Handle>> {
63            self.table.imports(self.id)
64        }
65
66        pub fn bodies(&self) -> Option<&'a Expr> {
67            self.table.body(self.id)
68        }
69
70        pub fn span(&self) -> Option<&Span> {
71            self.table.span(self.id)
72        }
73
74        pub fn meta(&self) -> Option<&[Meta]> {
75            self.table.meta(self.id)
76        }
77
78        pub fn source(&self) -> Option<&Source<'a>> {
79            self.table.source(self.id)
80        }
81
82        pub fn name(&self) -> Option<Sym> {
83            self.table.name(self.id)
84        }
85    };
86}
87
88impl<'t, 'a> Entry<'t, 'a> {
89    pub const fn new(table: &'t Table<'a>, id: Handle) -> Self {
90        Self { table, id }
91    }
92
93    impl_entry_!();
94
95    pub const fn with_id(&self, id: Handle) -> Entry<'t, 'a> {
96        Self { table: self.table, id }
97    }
98
99    pub fn nav(&self, path: &[PathPart]) -> Option<Entry<'t, 'a>> {
100        Some(Entry { id: self.table.nav(self.id, path)?, table: self.table })
101    }
102
103    pub fn parent(&self) -> Option<Entry<'t, 'a>> {
104        Some(Entry { id: *self.table.parent(self.id)?, ..*self })
105    }
106
107    pub fn ty(&self) -> Option<&'t TypeKind> {
108        self.table.ty(self.id)
109    }
110
111    pub fn impl_target(&self) -> Option<Entry<'_, 'a>> {
112        Some(Entry { id: self.table.impl_target(self.id)?, ..*self })
113    }
114
115    pub fn selfty(&self) -> Option<Entry<'_, 'a>> {
116        Some(Entry { id: self.table.selfty(self.id)?, ..*self })
117    }
118}
119
120#[derive(Debug)]
121pub struct EntryMut<'t, 'a> {
122    table: &'t mut Table<'a>,
123    id: Handle,
124}
125
126impl<'t, 'a> EntryMut<'t, 'a> {
127    pub fn new(table: &'t mut Table<'a>, id: Handle) -> Self {
128        Self { table, id }
129    }
130
131    impl_entry_!();
132
133    pub fn ty(&self) -> Option<&TypeKind> {
134        self.table.ty(self.id)
135    }
136
137    pub fn inner_mut(&mut self) -> &mut Table<'a> {
138        self.table
139    }
140
141    pub fn as_ref(&self) -> Entry<'_, 'a> {
142        Entry { table: self.table, id: self.id }
143    }
144
145    /// Evaluates a [TypeExpression] in this entry's context
146    pub fn evaluate<Out>(&mut self, ty: &impl TypeExpression<Out>) -> Result<Out, tex::Error> {
147        let Self { table, id } = self;
148        ty.evaluate(table, *id)
149    }
150
151    pub fn categorize(&mut self) -> Result<(), cat::Error> {
152        cat::categorize(self.table, self.id)
153    }
154
155    /// Constructs a new Handle with the provided parent [Handle]
156    pub fn with_id(&mut self, parent: Handle) -> EntryMut<'_, 'a> {
157        EntryMut { table: self.table, id: parent }
158    }
159
160    pub fn nav(&mut self, path: &[PathPart]) -> Option<EntryMut<'_, 'a>> {
161        Some(EntryMut { id: self.table.nav(self.id, path)?, table: self.table })
162    }
163
164    pub fn new_entry(&mut self, kind: NodeKind) -> EntryMut<'_, 'a> {
165        let id = self.table.new_entry(self.id, kind);
166        self.with_id(id)
167    }
168
169    pub fn add_child(&mut self, name: Sym, child: Handle) -> Option<Handle> {
170        self.table.add_child(self.id, name, child)
171    }
172
173    pub fn set_body(&mut self, body: &'a Expr) -> Option<&'a Expr> {
174        self.table.set_body(self.id, body)
175    }
176
177    pub fn set_ty(&mut self, kind: TypeKind) -> Option<TypeKind> {
178        self.table.set_ty(self.id, kind)
179    }
180
181    pub fn set_span(&mut self, span: Span) -> Option<Span> {
182        self.table.set_span(self.id, span)
183    }
184
185    pub fn set_meta(&mut self, meta: &'a [Meta]) -> Option<&'a [Meta]> {
186        self.table.set_meta(self.id, meta)
187    }
188
189    pub fn set_source(&mut self, source: Source<'a>) -> Option<Source<'a>> {
190        self.table.set_source(self.id, source)
191    }
192
193    pub fn set_impl_target(&mut self, target: Handle) -> Option<Handle> {
194        self.table.set_impl_target(self.id, target)
195    }
196
197    pub fn mark_unchecked(&mut self) {
198        self.table.mark_unchecked(self.id)
199    }
200
201    pub fn mark_use_item(&mut self) {
202        self.table.mark_use_item(self.id)
203    }
204
205    pub fn mark_impl_item(&mut self) {
206        self.table.mark_impl_item(self.id)
207    }
208
209    pub fn mark_lang_item(&mut self, lang_item: &'static str) {
210        self.table.mark_lang_item(lang_item, self.id)
211    }
212}