1use crate::source_map::SourceMap;
18
19use core::{
20 borrow::Borrow,
21 cmp::PartialEq,
22 fmt,
23 hash::{Hash, Hasher},
24 num::NonZeroU32,
25 ops::Deref,
26 str,
27};
28use fxhash::FxBuildHasher;
29use indexmap::IndexSet;
30use serde::{Deserialize, Deserializer, Serialize, Serializer};
31use std::cell::RefCell;
32
33macro_rules! consts {
37 ($val: expr, $sym:ident $(,)?) => {
38 #[allow(non_upper_case_globals)]
39 pub const $sym: $crate::symbol::Symbol = $crate::symbol::Symbol::new($val);
40 };
41 ($val: expr, $sym:ident: $_s:literal $(,)?) => {
42 consts!($val, $sym);
43 };
44 ($val: expr, $sym:ident: $_s:literal, $($rest:tt)*) => {
45 consts!($val, $sym);
46 consts!($val + 1, $($rest)*);
47 };
48 ($val: expr, $sym:ident, $($rest:tt)*) => {
49 consts!($val, $sym);
50 consts!($val + 1, $($rest)*);
51 };
52}
53
54macro_rules! strings {
58 ([$($acc:expr),*] []) => {
63 [$($acc),*]
64 };
65 ([$($acc:expr),*] [$_sym:ident: $string:literal, $($rest:tt)*]) => {
68 strings!([$($acc,)* $string] [$($rest)*])
69 };
70 ([$($acc:expr),*] [$sym:ident, $($rest:tt)*]) => {
72 strings!([$($acc,)* stringify!($sym)] [$($rest)*])
73 };
74 ([$($acc:expr),*] [$_sym:ident: $string:literal $(,)?]) => {
76 strings!([$($acc,)* $string] [])
77 };
78 ([$($acc:expr),*] [$sym:ident $(,)?]) => {
81 strings!([$($acc,)* stringify!($sym)] [])
82 };
83}
84
85macro_rules! symbols {
94 ($($symbols:tt)*) => {
95 const PRE_DEFINED: &[&str] = &strings!([] [$($symbols)*]);
96
97 pub mod sym {
98 consts!(0, $($symbols)*);
99 }
100 };
101}
102
103symbols! {
104 abs,
106 abs_wrapped,
107 double,
108 inv,
109 neg,
110 not,
111 square,
112 square_root,
113
114 add,
116 add_wrapped,
117 and,
118 div,
119 div_wrapped,
120 eq,
121 gte,
122 gt,
123 lte,
124 lt,
125 Mod: "mod",
126 mul,
127 mul_wrapped,
128 nand,
129 neq,
130 nor,
131 or,
132 pow,
133 pow_wrapped,
134 rem,
135 rem_wrapped,
136 shl,
137 shl_wrapped,
138 shr,
139 shr_wrapped,
140 sub,
141 sub_wrapped,
142 xor,
143
144 GEN,
146
147 BHP256,
149 BHP512,
150 BHP768,
151 BHP1024,
152 ChaCha,
153 commit_to_address,
154 commit_to_field,
155 commit_to_group,
156 contains,
157 get,
158 get_or_use,
159 hash_to_address,
160 hash_to_field,
161 hash_to_group,
162 hash_to_i8,
163 hash_to_i16,
164 hash_to_i32,
165 hash_to_i64,
166 hash_to_i128,
167 hash_to_u8,
168 hash_to_u16,
169 hash_to_u32,
170 hash_to_u64,
171 hash_to_u128,
172 hash_to_scalar,
173 Keccak256,
174 Keccak384,
175 Keccak512,
176 Mapping,
177 Pedersen64,
178 Pedersen128,
179 Poseidon2,
180 Poseidon4,
181 Poseidon8,
182 rand_address,
183 rand_bool,
184 rand_field,
185 rand_group,
186 rand_i8,
187 rand_i16,
188 rand_i32,
189 rand_i64,
190 rand_i128,
191 rand_scalar,
192 rand_u8,
193 rand_u16,
194 rand_u32,
195 rand_u64,
196 rand_u128,
197 remove,
198 set,
199 SHA3_256,
200 SHA3_384,
201 SHA3_512,
202 to_x_coordinate,
203 to_y_coordinate,
204 verify,
205 Await: "await",
206
207 CheatCode,
209 print_mapping,
210 set_block_height,
211
212 address,
214 bool,
215 field,
216 group,
217 i8,
218 i16,
219 i32,
220 i64,
221 i128,
222 Future,
223 Fn,
224 record,
225 scalar,
226 signature,
227 string,
228 Struct: "struct",
229 u8,
230 u16,
231 u32,
232 u64,
233 u128,
234
235 False: "false",
237 True: "true",
238
239 should_fail,
241 test,
242
243 private_key,
245
246 As: "as",
248 assert,
249 assert_eq,
250 assert_neq,
251 caller,
252 Const: "const",
253 constant,
254 decrement,
255 Else: "else",
256 For: "for",
257 function,
258 If: "if",
259 In: "in",
260 import,
261 increment,
262 inline,
263 input,
264 Let: "let",
265 leo,
266 main,
267 mapping,
268 Mut: "mut",
269 Return: "return",
270 script,
271 SelfLower: "self",
272 SelfUpper: "Self",
273 signer,
274 Star: "*",
275 transition,
276 Type: "type",
277
278 aleo,
279 public,
280 private,
281 owner,
282 _nonce,
283 program,
284 stub,
285 block,
286 height,
287 network,
288 id,
289}
290
291#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
296pub struct Symbol(
297 #[serde(deserialize_with = "Symbol::serde_to_symbol")]
298 #[serde(serialize_with = "Symbol::serde_from_symbol")]
299 NonZeroU32,
300);
301
302impl Default for Symbol {
303 fn default() -> Self {
304 Symbol(NonZeroU32::MIN)
305 }
306}
307
308impl Symbol {
309 pub const fn new(index: u32) -> Self {
311 let index = index.saturating_add(1);
312 Self(match NonZeroU32::new(index) {
313 None => unreachable!(),
314 Some(x) => x,
315 })
316 }
317
318 pub fn intern(string: &str) -> Self {
320 with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
321 }
322
323 pub fn as_str<R>(self, s: &SessionGlobals, with: impl FnOnce(&str) -> R) -> R {
325 s.symbol_interner.get(self, with)
326 }
327
328 pub const fn as_u32(self) -> u32 {
330 self.0.get() - 1
331 }
332
333 fn serde_to_symbol<'de, D: Deserializer<'de>>(de: D) -> Result<NonZeroU32, D::Error> {
334 Ok(Symbol::intern(<&str>::deserialize(de)?).0)
335 }
336
337 fn serde_from_symbol<S: Serializer>(index: &NonZeroU32, ser: S) -> Result<S::Ok, S::Error> {
338 with_session_globals(|sg| Self(*index).as_str(sg, |s| ser.serialize_str(s)))
339 }
340}
341
342impl fmt::Debug for Symbol {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 with_session_globals(|s| self.as_str(s, |s| fmt::Debug::fmt(s, f)))
345 }
346}
347
348impl fmt::Display for Symbol {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 with_session_globals(|s| self.as_str(s, |s| fmt::Display::fmt(s, f)))
351 }
352}
353
354pub struct SessionGlobals {
356 symbol_interner: Interner,
358 pub source_map: SourceMap,
360}
361
362impl Default for SessionGlobals {
363 fn default() -> Self {
364 Self { symbol_interner: Interner::prefilled(), source_map: SourceMap::default() }
365 }
366}
367
368scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
369
370#[inline]
372pub fn create_session_if_not_set_then<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
373 if !SESSION_GLOBALS.is_set() {
374 let sg = SessionGlobals::default();
375 SESSION_GLOBALS.set(&sg, || SESSION_GLOBALS.with(f))
376 } else {
377 SESSION_GLOBALS.with(f)
378 }
379}
380
381#[inline]
383pub fn with_session_globals<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
384 SESSION_GLOBALS.with(f)
385}
386
387#[derive(Eq)]
391enum InternedStr {
392 Static(&'static str),
394 Owned(Box<str>),
396}
397
398impl Borrow<str> for InternedStr {
399 fn borrow(&self) -> &str {
400 self.deref()
401 }
402}
403
404impl Deref for InternedStr {
405 type Target = str;
406
407 fn deref(&self) -> &Self::Target {
408 match self {
409 Self::Static(s) => s,
410 Self::Owned(s) => s,
411 }
412 }
413}
414
415impl PartialEq for InternedStr {
416 fn eq(&self, other: &InternedStr) -> bool {
417 self.deref() == other.deref()
418 }
419}
420
421impl Hash for InternedStr {
422 fn hash<H: Hasher>(&self, state: &mut H) {
423 self.deref().hash(state);
424 }
425}
426
427struct InnerInterner {
430 set: IndexSet<InternedStr, FxBuildHasher>,
434}
435
436struct Interner {
438 inner: RefCell<InnerInterner>,
439}
440
441impl Interner {
442 fn prefilled() -> Self {
444 Self::prefill(PRE_DEFINED)
445 }
446
447 fn prefill(init: &[&'static str]) -> Self {
449 let inner = InnerInterner {
450 set: init.iter().copied().map(InternedStr::Static).collect(),
452 };
453 Self { inner: RefCell::new(inner) }
454 }
455
456 fn intern(&self, string: &str) -> Symbol {
458 let InnerInterner { set } = &mut *self.inner.borrow_mut();
459
460 if let Some(sym) = set.get_index_of(string) {
461 return Symbol::new(sym as u32);
463 }
464
465 Symbol::new(set.insert_full(InternedStr::Owned(string.into())).0 as u32)
466 }
467
468 fn get<R>(&self, symbol: Symbol, with: impl FnOnce(&str) -> R) -> R {
470 let set = &self.inner.borrow().set;
471 with(set.get_index(symbol.as_u32() as usize).unwrap())
472 }
473}