1use std::rc::Rc;
2
3use rustc_hash::{FxHashMap, FxHashSet};
4
5use super::saved_bindings::{BindingTables, SavedBindings};
6use super::{Builtin, KernelForm, KernelType, ModuleId};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
9pub struct VariantInfo {
10 pub owner: BindingId,
11 pub index: usize,
12 pub arity: usize,
13}
14use crate::source::Span;
15
16#[derive(
17 Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
18)]
19pub struct BindingId(u32);
20
21impl BindingId {
22 pub fn from_index(index: u32) -> Self {
23 Self(index)
24 }
25
26 pub fn index(self) -> u32 {
27 self.0
28 }
29}
30
31#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
32pub enum Namespace {
33 Value,
34 Type,
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
38pub enum Declaration {
39 Value,
40 Macro,
41 Type,
42}
43
44impl Declaration {
45 pub fn namespace(self) -> Namespace {
46 match self {
47 Self::Value | Self::Macro => Namespace::Value,
48 Self::Type => Namespace::Type,
49 }
50 }
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
54pub enum BindingKind {
55 KernelForm(KernelForm),
56 KernelType(KernelType),
57 Boolean(bool),
58 CodeBuiltin(Builtin),
59 Macro(ModuleId),
60 Global(ModuleId),
61 Local,
62 Struct(ModuleId),
63 Enum(ModuleId),
64 Variant(ModuleId, VariantInfo),
65 Trait(ModuleId),
66 RustType(ModuleId),
67 TypeVariable,
68 AssociatedType,
69 Lifetime,
70}
71
72#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
73pub struct BindingInfo {
74 name: Rc<str>,
75 kind: BindingKind,
76 span: Option<Span>,
77}
78
79impl BindingInfo {
80 pub fn new(name: Rc<str>, kind: BindingKind, span: Option<Span>) -> Self {
81 Self { name, kind, span }
82 }
83
84 pub fn name(&self) -> &str {
85 &self.name
86 }
87
88 pub fn shared_name(&self) -> Rc<str> {
89 Rc::clone(&self.name)
90 }
91
92 pub fn kind(&self) -> BindingKind {
93 self.kind
94 }
95
96 pub fn span(&self) -> Option<Span> {
97 self.span
98 }
99}
100
101#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
102pub struct BindingArena {
103 #[serde(skip)]
104 saved: Rc<SavedBindings>,
105 infos: Vec<BindingInfo>,
106 introduced: FxHashSet<BindingId>,
107 answering_macros: FxHashMap<BindingId, BindingId>,
108}
109
110impl BindingArena {
111 pub fn add(&mut self, info: BindingInfo) -> BindingId {
112 let index = self.saved.count() + self.infos.len();
113 self.infos.push(info);
114 BindingId(u32::try_from(index).expect("fewer than 2^32 bindings"))
115 }
116
117 pub fn take_saved(&mut self) -> BindingTables {
118 let tables = BindingTables::of(self.infos.iter());
119 self.infos.clear();
120 tables
121 }
122
123 pub fn adopt_saved(&mut self, saved: SavedBindings) {
124 assert!(
125 self.infos.is_empty(),
126 "saved bindings come before any other"
127 );
128 self.saved = Rc::new(saved);
129 }
130
131 pub fn ids(&self) -> impl Iterator<Item = BindingId> {
132 let count = self.saved.count() + self.infos.len();
133 (0..count).map(|index| BindingId(u32::try_from(index).expect("fewer than 2^32 bindings")))
134 }
135
136 pub fn is_saved(&self, id: BindingId) -> bool {
137 (id.0 as usize) < self.saved.count()
138 }
139
140 #[cfg(test)]
141 pub fn is_decoded(&self, id: BindingId) -> bool {
142 (id.0 as usize) >= self.saved.count() || self.saved.is_decoded(id.0 as usize)
143 }
144
145 #[inline]
146 pub fn get(&self, id: BindingId) -> &BindingInfo {
147 let index = id.0 as usize;
148 match index.checked_sub(self.saved.count()) {
149 Some(own) => &self.infos[own],
150 None => self.saved.get(index),
151 }
152 }
153
154 pub fn mark_introduced(&mut self, id: BindingId) {
155 self.introduced.insert(id);
156 }
157
158 pub fn is_introduced(&self, id: BindingId) -> bool {
159 self.introduced.contains(&id)
160 }
161
162 pub fn record_answering_macro(&mut self, function: BindingId, answering: BindingId) {
163 self.answering_macros.insert(function, answering);
164 }
165
166 pub fn answering_macro(&self, function: BindingId) -> Option<BindingId> {
167 self.answering_macros.get(&function).copied()
168 }
169}