1use std::any::Any;
2use std::any::TypeId;
3use std::borrow::Borrow;
4use std::collections::hash_map::DefaultHasher;
5use std::collections::HashMap;
6use std::hash::Hash;
7use std::hash::Hasher;
8use std::ops::Index;
9
10use ena::unify::UnifyKey;
11
12pub trait ASTKey {
15 fn eq(&self, other: &dyn ASTKey) -> bool;
16 fn hash(&self) -> u64;
17 fn as_any(&self) -> &dyn Any;
18}
19
20impl<T: Eq + Hash + 'static> ASTKey for T {
21 fn eq(&self, other: &dyn ASTKey) -> bool {
22 if let Some(other) = other.as_any().downcast_ref::<T>() {
23 self == other
24 } else {
25 false
26 }
27 }
28 fn hash(&self) -> u64 {
29 let mut h = DefaultHasher::new();
30 Hash::hash(&(TypeId::of::<T>(), self), &mut h);
31 h.finish()
32 }
33
34 fn as_any(&self) -> &dyn Any {
35 self
36 }
37}
38
39impl<'a> PartialEq for &'a dyn ASTKey {
40 fn eq(&self, other: &Self) -> bool {
41 ASTKey::eq(*self, *other)
42 }
43}
44
45impl<'a> Eq for &'a dyn ASTKey {}
46
47impl<'a> Hash for &'a dyn ASTKey {
48 fn hash<H: Hasher>(&self, state: &mut H) {
49 let key_hash = ASTKey::hash(*self);
50 state.write_u64(key_hash)
51 }
52}
53
54fn eq_box(elt_a: &Box<dyn ASTKey>, elt_b: &Box<dyn ASTKey>) -> bool {
55 ASTKey::eq(&*elt_a, &*elt_b.borrow())
56}
57
58fn hash_box<H: Hasher>(elt: &Box<dyn ASTKey>, state: &mut H) {
59 Hash::hash(&elt, state)
60}
61
62impl Hash for Box<dyn ASTKey> {
63 fn hash<H: Hasher>(&self, state: &mut H) {
64 hash_box(self, state)
65 }
66}
67
68impl PartialEq for Box<dyn ASTKey> {
69 fn eq(&self, other: &Self) -> bool {
70 eq_box(self, other)
71 }
72}
73
74impl Eq for Box<dyn ASTKey> {}
75
76#[derive(Debug)]
78pub struct ScopedContext<K: Eq + Hash, L>(Vec<HashMap<K, L>>);
79
80impl<K: Eq + Hash, L> Default for ScopedContext<K, L> {
81 fn default() -> Self {
82 ScopedContext(vec![HashMap::new()])
83 }
84}
85
86impl<'a, 'b, K: Eq + Hash, L> Index<&'a K> for ScopedContext<K, &'b L> {
87 type Output = L;
88
89 fn index(&self, index: &'a K) -> &'b Self::Output {
90 self.lookup(index).unwrap()
91 }
92}
93
94impl<K: Eq + Hash, L> ScopedContext<K, L> {
95 pub fn open_scope(&mut self) {
96 self.0.push(HashMap::new())
97 }
98 pub fn close_scope(&mut self) {
99 self.0.pop();
100 }
101
102 pub fn add_binding(&mut self, var: K, value: L) {
103 self.0.last_mut().unwrap().insert(var, value);
104 }
105}
106
107impl<K: Eq + Hash, L: Clone> ScopedContext<K, L> {
108 pub fn lookup(&self, ident: &K) -> Option<L> {
109 for table in self.0.iter().rev() {
110 match table.get(ident) {
111 Some(result) => return Some(result.clone()),
112 _ => (),
113 }
114 }
115 None
116 }
117}
118
119#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
121pub struct Label(usize);
122
123impl std::fmt::Display for Label {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "A{}", self.0)
126 }
127}
128
129impl Label {
130 pub fn new() -> Self {
131 Label(0)
132 }
133 pub fn incr(&mut self) {
134 self.0 += 1
135 }
136 pub fn of_raw(v: usize) -> Self {
137 Label(v)
138 }
139 pub fn to_raw(self) -> usize {
140 self.0
141 }
142}
143
144impl UnifyKey for Label {
145 type Value = Option<crate::typ::RustType>;
146
147 fn index(&self) -> u32 {
148 self.0 as u32
149 }
150
151 fn from_index(u: u32) -> Self {
152 Label(u as usize)
153 }
154
155 fn tag() -> &'static str {
156 todo!()
157 }
158}