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 Optional,
178 Pedersen64,
179 Pedersen128,
180 Poseidon2,
181 Poseidon4,
182 Poseidon8,
183 rand_address,
184 rand_bool,
185 rand_field,
186 rand_group,
187 rand_i8,
188 rand_i16,
189 rand_i32,
190 rand_i64,
191 rand_i128,
192 rand_scalar,
193 rand_u8,
194 rand_u16,
195 rand_u32,
196 rand_u64,
197 rand_u128,
198 remove,
199 set,
200 SHA3_256,
201 SHA3_384,
202 SHA3_512,
203 to_x_coordinate,
204 to_y_coordinate,
205 verify,
206 Await: "await",
207 unwrap,
208 unwrap_or,
209
210 CheatCode,
212 print_mapping,
213 set_block_height,
214
215 address,
217 bool,
218 field,
219 group,
220 i8,
221 i16,
222 i32,
223 i64,
224 i128,
225 Future,
226 Fn,
227 record,
228 scalar,
229 signature,
230 string,
231 Struct: "struct",
232 u8,
233 u16,
234 u32,
235 u64,
236 u128,
237
238 False: "false",
240 True: "true",
241 None: "none",
242
243 should_fail,
245 test,
246 noupgrade,
247 custom,
248 admin,
249 key,
250
251 private_key,
253
254 As: "as",
256 assert,
257 assert_eq,
258 assert_neq,
259 Async: "async",
260 caller,
261 Const: "const",
262 constant,
263 constructor,
264 decrement,
265 Else: "else",
266 For: "for",
267 function,
268 If: "if",
269 In: "in",
270 import,
271 increment,
272 inline,
273 input,
274 Let: "let",
275 leo,
276 main,
277 mapping,
278 Mut: "mut",
279 Return: "return",
280 script,
281 SelfLower: "self",
282 SelfUpper: "Self",
283 signer,
284 Star: "*",
285 transition,
286 Type: "type",
287
288 aleo,
289 public,
290 private,
291 owner,
292 _nonce,
293 program,
294 ProgramCore: "Program",
295 stub,
296 block,
297 height,
298 network,
299 id,
300 checksum,
301 edition,
302 program_owner,
303}
304
305#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
310pub struct Symbol(
311 #[serde(deserialize_with = "Symbol::serde_to_symbol")]
312 #[serde(serialize_with = "Symbol::serde_from_symbol")]
313 NonZeroU32,
314);
315
316impl Default for Symbol {
317 fn default() -> Self {
318 Symbol(NonZeroU32::MIN)
319 }
320}
321
322impl Symbol {
323 pub const fn new(index: u32) -> Self {
325 let index = index.saturating_add(1);
326 Self(match NonZeroU32::new(index) {
327 None => unreachable!(),
328 Some(x) => x,
329 })
330 }
331
332 pub fn intern(string: &str) -> Self {
334 with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
335 }
336
337 pub fn as_str<R>(self, s: &SessionGlobals, with: impl FnOnce(&str) -> R) -> R {
339 s.symbol_interner.get(self, with)
340 }
341
342 pub const fn as_u32(self) -> u32 {
344 self.0.get() - 1
345 }
346
347 fn serde_to_symbol<'de, D: Deserializer<'de>>(de: D) -> Result<NonZeroU32, D::Error> {
348 Ok(Symbol::intern(<&str>::deserialize(de)?).0)
349 }
350
351 fn serde_from_symbol<S: Serializer>(index: &NonZeroU32, ser: S) -> Result<S::Ok, S::Error> {
352 with_session_globals(|sg| Self(*index).as_str(sg, |s| ser.serialize_str(s)))
353 }
354}
355
356impl fmt::Debug for Symbol {
357 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358 with_session_globals(|s| self.as_str(s, |s| fmt::Debug::fmt(s, f)))
359 }
360}
361
362impl fmt::Display for Symbol {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 with_session_globals(|s| self.as_str(s, |s| fmt::Display::fmt(s, f)))
365 }
366}
367
368pub struct SessionGlobals {
370 symbol_interner: Interner,
372 pub source_map: SourceMap,
374}
375
376impl Default for SessionGlobals {
377 fn default() -> Self {
378 Self { symbol_interner: Interner::prefilled(), source_map: SourceMap::default() }
379 }
380}
381
382scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
383
384#[inline]
386pub fn create_session_if_not_set_then<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
387 if !SESSION_GLOBALS.is_set() {
388 let sg = SessionGlobals::default();
389 SESSION_GLOBALS.set(&sg, || SESSION_GLOBALS.with(f))
390 } else {
391 SESSION_GLOBALS.with(f)
392 }
393}
394
395#[inline]
397pub fn with_session_globals<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
398 SESSION_GLOBALS.with(f)
399}
400
401#[derive(Eq)]
405enum InternedStr {
406 Static(&'static str),
408 Owned(Box<str>),
410}
411
412impl Borrow<str> for InternedStr {
413 fn borrow(&self) -> &str {
414 self.deref()
415 }
416}
417
418impl Deref for InternedStr {
419 type Target = str;
420
421 fn deref(&self) -> &Self::Target {
422 match self {
423 Self::Static(s) => s,
424 Self::Owned(s) => s,
425 }
426 }
427}
428
429impl PartialEq for InternedStr {
430 fn eq(&self, other: &InternedStr) -> bool {
431 self.deref() == other.deref()
432 }
433}
434
435impl Hash for InternedStr {
436 fn hash<H: Hasher>(&self, state: &mut H) {
437 self.deref().hash(state);
438 }
439}
440
441struct InnerInterner {
444 set: IndexSet<InternedStr, FxBuildHasher>,
448}
449
450struct Interner {
452 inner: RefCell<InnerInterner>,
453}
454
455impl Interner {
456 fn prefilled() -> Self {
458 Self::prefill(PRE_DEFINED)
459 }
460
461 fn prefill(init: &[&'static str]) -> Self {
463 let inner = InnerInterner {
464 set: init.iter().copied().map(InternedStr::Static).collect(),
466 };
467 Self { inner: RefCell::new(inner) }
468 }
469
470 fn intern(&self, string: &str) -> Symbol {
472 let InnerInterner { set } = &mut *self.inner.borrow_mut();
473
474 if let Some(sym) = set.get_index_of(string) {
475 return Symbol::new(sym as u32);
477 }
478
479 Symbol::new(set.insert_full(InternedStr::Owned(string.into())).0 as u32)
480 }
481
482 fn get<R>(&self, symbol: Symbol, with: impl FnOnce(&str) -> R) -> R {
484 let set = &self.inner.borrow().set;
485 with(set.get_index(symbol.as_u32() as usize).unwrap())
486 }
487}