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 display;
24
25impl Handle {
26    pub const fn to_entry<'t, 'a>(self, table: &'t Table<'a>) -> Entry<'t, 'a> {
27        Entry { id: self, table }
28    }
29    pub fn to_entry_mut<'t, 'a>(self, table: &'t mut Table<'a>) -> EntryMut<'t, 'a> {
30        EntryMut { id: self, table }
31    }
32}
33
34#[derive(Debug)]
35pub struct Entry<'t, 'a> {
36    table: &'t Table<'a>,
37    id: Handle,
38}
39
40impl<'t, 'a> Entry<'t, 'a> {
41    pub const fn new(table: &'t Table<'a>, id: Handle) -> Self {
42        Self { table, id }
43    }
44
45    pub const fn id(&self) -> Handle {
46        self.id
47    }
48
49    pub fn inner(&self) -> &'t Table<'a> {
50        self.table
51    }
52
53    pub const fn with_id(&self, id: Handle) -> Entry<'t, 'a> {
54        Self { table: self.table, id }
55    }
56
57    pub fn nav(&self, path: &[PathPart]) -> Option<Entry<'t, 'a>> {
58        Some(Entry { id: self.table.nav(self.id, path)?, table: self.table })
59    }
60
61    pub const fn root(&self) -> Handle {
62        self.table.root()
63    }
64
65    pub fn kind(&self) -> Option<&'t NodeKind> {
66        self.table.kind(self.id)
67    }
68
69    pub fn parent(&self) -> Option<Entry<'t, 'a>> {
70        Some(Entry { id: *self.table.parent(self.id)?, ..*self })
71    }
72
73    pub fn children(&self) -> Option<&'t HashMap<Sym, Handle>> {
74        self.table.children(self.id)
75    }
76
77    pub fn imports(&self) -> Option<&'t HashMap<Sym, Handle>> {
78        self.table.imports(self.id)
79    }
80
81    pub fn bodies(&self) -> Option<&'a Expr> {
82        self.table.body(self.id)
83    }
84
85    pub fn ty(&self) -> Option<&'t TypeKind> {
86        self.table.ty(self.id)
87    }
88
89    pub fn span(&self) -> Option<&'t Span> {
90        self.table.span(self.id)
91    }
92
93    pub fn meta(&self) -> Option<&'a [Meta]> {
94        self.table.meta(self.id)
95    }
96
97    pub fn source(&self) -> Option<&'t Source<'a>> {
98        self.table.source(self.id)
99    }
100
101    pub fn impl_target(&self) -> Option<Entry<'_, 'a>> {
102        Some(Entry { id: self.table.impl_target(self.id)?, ..*self })
103    }
104
105    pub fn selfty(&self) -> Option<Entry<'_, 'a>> {
106        Some(Entry { id: self.table.selfty(self.id)?, ..*self })
107    }
108
109    pub fn name(&self) -> Option<Sym> {
110        self.table.name(self.id)
111    }
112}
113
114#[derive(Debug)]
115pub struct EntryMut<'t, 'a> {
116    table: &'t mut Table<'a>,
117    id: Handle,
118}
119
120impl<'t, 'a> EntryMut<'t, 'a> {
121    pub fn new(table: &'t mut Table<'a>, id: Handle) -> Self {
122        Self { table, id }
123    }
124
125    pub fn as_ref(&self) -> Entry<'_, 'a> {
126        Entry { table: self.table, id: self.id }
127    }
128
129    pub const fn id(&self) -> Handle {
130        self.id
131    }
132
133    /// Evaluates a [TypeExpression] in this entry's context
134    pub fn evaluate<Out>(&mut self, ty: &impl TypeExpression<Out>) -> Result<Out, tex::Error> {
135        let Self { table, id } = self;
136        ty.evaluate(table, *id)
137    }
138
139    pub fn categorize(&mut self) -> Result<(), cat::Error> {
140        cat::categorize(self.table, self.id)
141    }
142
143    /// Constructs a new Handle with the provided parent [Handle]
144    pub fn with_id(&mut self, parent: Handle) -> EntryMut<'_, 'a> {
145        EntryMut { table: self.table, id: parent }
146    }
147
148    pub fn nav(&mut self, path: &[PathPart]) -> Option<EntryMut<'_, 'a>> {
149        Some(EntryMut { id: self.table.nav(self.id, path)?, table: self.table })
150    }
151
152    pub fn new_entry(&mut self, kind: NodeKind) -> EntryMut<'_, 'a> {
153        let id = self.table.new_entry(self.id, kind);
154        self.with_id(id)
155    }
156
157    pub fn add_child(&mut self, name: Sym, child: Handle) -> Option<Handle> {
158        self.table.add_child(self.id, name, child)
159    }
160
161    pub fn set_body(&mut self, body: &'a Expr) -> Option<&'a Expr> {
162        self.table.set_body(self.id, body)
163    }
164
165    pub fn set_ty(&mut self, kind: TypeKind) -> Option<TypeKind> {
166        self.table.set_ty(self.id, kind)
167    }
168
169    pub fn set_span(&mut self, span: Span) -> Option<Span> {
170        self.table.set_span(self.id, span)
171    }
172
173    pub fn set_meta(&mut self, meta: &'a [Meta]) -> Option<&'a [Meta]> {
174        self.table.set_meta(self.id, meta)
175    }
176
177    pub fn set_source(&mut self, source: Source<'a>) -> Option<Source<'a>> {
178        self.table.set_source(self.id, source)
179    }
180
181    pub fn set_impl_target(&mut self, target: Handle) -> Option<Handle> {
182        self.table.set_impl_target(self.id, target)
183    }
184
185    pub fn mark_use_item(&mut self) {
186        self.table.mark_use_item(self.id)
187    }
188
189    pub fn mark_impl_item(&mut self) {
190        self.table.mark_impl_item(self.id)
191    }
192}