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 ECDSA,
158 get,
159 get_or_use,
160 hash_to_address,
161 hash_to_field,
162 hash_to_group,
163 hash_to_i8,
164 hash_to_i16,
165 hash_to_i32,
166 hash_to_i64,
167 hash_to_i128,
168 hash_to_u8,
169 hash_to_u16,
170 hash_to_u32,
171 hash_to_u64,
172 hash_to_u128,
173 hash_to_scalar,
174 hash_to_address_raw,
175 hash_to_field_raw,
176 hash_to_group_raw,
177 hash_to_i8_raw,
178 hash_to_i16_raw,
179 hash_to_i32_raw,
180 hash_to_i64_raw,
181 hash_to_i128_raw,
182 hash_to_u8_raw,
183 hash_to_u16_raw,
184 hash_to_u32_raw,
185 hash_to_u64_raw,
186 hash_to_u128_raw,
187 hash_to_scalar_raw,
188 hash_native,
189 hash_native_raw,
190 Keccak256,
191 Keccak384,
192 Keccak512,
193 Mapping,
194 Storage,
195 Optional,
196 Vector,
197 Pedersen64,
198 Pedersen128,
199 Poseidon2,
200 Poseidon4,
201 Poseidon8,
202 rand_address,
203 rand_bool,
204 rand_field,
205 rand_group,
206 rand_i8,
207 rand_i16,
208 rand_i32,
209 rand_i64,
210 rand_i128,
211 rand_scalar,
212 rand_u8,
213 rand_u16,
214 rand_u32,
215 rand_u64,
216 rand_u128,
217 remove,
218 set,
219 SHA3_256,
220 SHA3_384,
221 SHA3_512,
222 to_x_coordinate,
223 to_y_coordinate,
224 verify,
225 verify_digest,
226 verify_digest_eth,
227 verify_keccak256,
228 verify_keccak256_raw,
229 verify_keccak256_eth,
230 verify_keccak256_eth_raw,
231 verify_keccak384,
232 verify_keccak384_raw,
233 verify_keccak384_eth,
234 verify_keccak384_eth_raw,
235 verify_keccak512,
236 verify_keccak512_raw,
237 verify_keccak512_eth,
238 verify_keccak512_eth_raw,
239 verify_sha3_256,
240 verify_sha3_256_raw,
241 verify_sha3_256_eth,
242 verify_sha3_256_eth_raw,
243 verify_sha3_384,
244 verify_sha3_384_raw,
245 verify_sha3_384_eth,
246 verify_sha3_384_eth_raw,
247 verify_sha3_512,
248 verify_sha3_512_raw,
249 verify_sha3_512_eth,
250 verify_sha3_512_eth_raw,
251 Serialize,
252 Deserialize,
253 to_bits,
254 to_bits_raw,
255 from_bits,
256 from_bits_raw,
257
258 Await: "await",
259 unwrap,
260 unwrap_or,
261 push,
262 len,
263 clear,
264 pop,
265 swap_remove,
266
267 CheatCode,
269 print_mapping,
270 set_block_height,
271 set_signer,
272
273 address,
275 bool,
276 field,
277 group,
278 i8,
279 i16,
280 i32,
281 i64,
282 i128,
283 Future,
284 Fn,
285 record,
286 scalar,
287 signature,
288 string,
289 Struct: "struct",
290 u8,
291 u16,
292 u32,
293 u64,
294 u128,
295
296 False: "false",
298 True: "true",
299 None: "none",
300
301 should_fail,
303 test,
304 noupgrade,
305 custom,
306 admin,
307 key,
308
309 private_key,
311
312 As: "as",
314 assert,
315 assert_eq,
316 assert_neq,
317 Async: "async",
318 caller,
319 Const: "const",
320 constant,
321 constructor,
322 decrement,
323 Else: "else",
324 For: "for",
325 function,
326 If: "if",
327 In: "in",
328 import,
329 increment,
330 inline,
331 input,
332 Let: "let",
333 leo,
334 main,
335 mapping,
336 storage,
337 Mut: "mut",
338 Return: "return",
339 script,
340 SelfLower: "self",
341 SelfUpper: "Self",
342 signer,
343 Star: "*",
344 transition,
345 Type: "type",
346
347 aleo,
348 public,
349 private,
350 owner,
351 _nonce,
352 program,
353 ProgramCore: "Program",
354 stub,
355 block,
356 height,
357 network,
358 id,
359 checksum,
360 edition,
361 program_owner,
362}
363
364#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
369pub struct Symbol(
370 #[serde(deserialize_with = "Symbol::serde_to_symbol")]
371 #[serde(serialize_with = "Symbol::serde_from_symbol")]
372 NonZeroU32,
373);
374
375impl Default for Symbol {
376 fn default() -> Self {
377 Symbol(NonZeroU32::MIN)
378 }
379}
380
381impl Symbol {
382 pub const fn new(index: u32) -> Self {
384 let index = index.saturating_add(1);
385 Self(match NonZeroU32::new(index) {
386 None => unreachable!(),
387 Some(x) => x,
388 })
389 }
390
391 pub fn intern(string: &str) -> Self {
393 with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
394 }
395
396 pub fn as_str<R>(self, s: &SessionGlobals, with: impl FnOnce(&str) -> R) -> R {
398 s.symbol_interner.get(self, with)
399 }
400
401 pub const fn as_u32(self) -> u32 {
403 self.0.get() - 1
404 }
405
406 fn serde_to_symbol<'de, D: Deserializer<'de>>(de: D) -> Result<NonZeroU32, D::Error> {
407 Ok(Symbol::intern(<&str>::deserialize(de)?).0)
408 }
409
410 fn serde_from_symbol<S: Serializer>(index: &NonZeroU32, ser: S) -> Result<S::Ok, S::Error> {
411 with_session_globals(|sg| Self(*index).as_str(sg, |s| ser.serialize_str(s)))
412 }
413}
414
415impl fmt::Debug for Symbol {
416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417 with_session_globals(|s| self.as_str(s, |s| fmt::Debug::fmt(s, f)))
418 }
419}
420
421impl fmt::Display for Symbol {
422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423 with_session_globals(|s| self.as_str(s, |s| fmt::Display::fmt(s, f)))
424 }
425}
426
427pub struct SessionGlobals {
429 symbol_interner: Interner,
431 pub source_map: SourceMap,
433}
434
435impl Default for SessionGlobals {
436 fn default() -> Self {
437 Self { symbol_interner: Interner::prefilled(), source_map: SourceMap::default() }
438 }
439}
440
441scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
442
443#[inline]
445pub fn create_session_if_not_set_then<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
446 if !SESSION_GLOBALS.is_set() {
447 let sg = SessionGlobals::default();
448 SESSION_GLOBALS.set(&sg, || SESSION_GLOBALS.with(f))
449 } else {
450 SESSION_GLOBALS.with(f)
451 }
452}
453
454#[inline]
456pub fn with_session_globals<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
457 SESSION_GLOBALS.with(f)
458}
459
460#[derive(Eq)]
464enum InternedStr {
465 Static(&'static str),
467 Owned(Box<str>),
469}
470
471impl Borrow<str> for InternedStr {
472 fn borrow(&self) -> &str {
473 self.deref()
474 }
475}
476
477impl Deref for InternedStr {
478 type Target = str;
479
480 fn deref(&self) -> &Self::Target {
481 match self {
482 Self::Static(s) => s,
483 Self::Owned(s) => s,
484 }
485 }
486}
487
488impl PartialEq for InternedStr {
489 fn eq(&self, other: &InternedStr) -> bool {
490 self.deref() == other.deref()
491 }
492}
493
494impl Hash for InternedStr {
495 fn hash<H: Hasher>(&self, state: &mut H) {
496 self.deref().hash(state);
497 }
498}
499
500struct InnerInterner {
503 set: IndexSet<InternedStr, FxBuildHasher>,
507}
508
509struct Interner {
511 inner: RefCell<InnerInterner>,
512}
513
514impl Interner {
515 fn prefilled() -> Self {
517 Self::prefill(PRE_DEFINED)
518 }
519
520 fn prefill(init: &[&'static str]) -> Self {
522 let inner = InnerInterner {
523 set: init.iter().copied().map(InternedStr::Static).collect(),
525 };
526 Self { inner: RefCell::new(inner) }
527 }
528
529 fn intern(&self, string: &str) -> Symbol {
531 let InnerInterner { set } = &mut *self.inner.borrow_mut();
532
533 if let Some(sym) = set.get_index_of(string) {
534 return Symbol::new(sym as u32);
536 }
537
538 Symbol::new(set.insert_full(InternedStr::Owned(string.into())).0 as u32)
539 }
540
541 fn get<R>(&self, symbol: Symbol, with: impl FnOnce(&str) -> R) -> R {
543 let set = &self.inner.borrow().set;
544 with(set.get_index(symbol.as_u32() as usize).unwrap())
545 }
546}