Skip to main content

knave_expand/core/
binding.rs

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}