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_to_bits,
189 hash_to_bits_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_block_timestamp,
272 set_signer,
273
274 address,
276 bool,
277 field,
278 group,
279 i8,
280 i16,
281 i32,
282 i64,
283 i128,
284 Future,
285 Fn,
286 record,
287 scalar,
288 signature,
289 string,
290 Struct: "struct",
291 u8,
292 u16,
293 u32,
294 u64,
295 u128,
296
297 False: "false",
299 True: "true",
300 None: "none",
301
302 should_fail,
304 test,
305 noupgrade,
306 custom,
307 admin,
308 key,
309
310 private_key,
312
313 As: "as",
315 assert,
316 assert_eq,
317 assert_neq,
318 Async: "async",
319 caller,
320 Const: "const",
321 constant,
322 constructor,
323 decrement,
324 Else: "else",
325 For: "for",
326 function,
327 If: "if",
328 In: "in",
329 import,
330 increment,
331 inline,
332 input,
333 Let: "let",
334 leo,
335 main,
336 mapping,
337 storage,
338 Mut: "mut",
339 Return: "return",
340 script,
341 SelfLower: "self",
342 SelfUpper: "Self",
343 signer,
344 Star: "*",
345 transition,
346 Type: "type",
347
348 aleo,
349 public,
350 private,
351 owner,
352 _nonce,
353 program,
354 ProgramCore: "Program",
355 stub,
356 block,
357 height,
358 timestamp,
359 network,
360 id,
361 checksum,
362 edition,
363 program_owner,
364}
365
366#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
371pub struct Symbol(
372 #[serde(deserialize_with = "Symbol::serde_to_symbol")]
373 #[serde(serialize_with = "Symbol::serde_from_symbol")]
374 NonZeroU32,
375);
376
377impl Default for Symbol {
378 fn default() -> Self {
379 Symbol(NonZeroU32::MIN)
380 }
381}
382
383impl Symbol {
384 pub const fn new(index: u32) -> Self {
386 let index = index.saturating_add(1);
387 Self(match NonZeroU32::new(index) {
388 None => unreachable!(),
389 Some(x) => x,
390 })
391 }
392
393 pub fn intern(string: &str) -> Self {
395 with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
396 }
397
398 pub fn as_str<R>(self, s: &SessionGlobals, with: impl FnOnce(&str) -> R) -> R {
400 s.symbol_interner.get(self, with)
401 }
402
403 pub const fn as_u32(self) -> u32 {
405 self.0.get() - 1
406 }
407
408 fn serde_to_symbol<'de, D: Deserializer<'de>>(de: D) -> Result<NonZeroU32, D::Error> {
409 Ok(Symbol::intern(<&str>::deserialize(de)?).0)
410 }
411
412 fn serde_from_symbol<S: Serializer>(index: &NonZeroU32, ser: S) -> Result<S::Ok, S::Error> {
413 with_session_globals(|sg| Self(*index).as_str(sg, |s| ser.serialize_str(s)))
414 }
415}
416
417impl fmt::Debug for Symbol {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 with_session_globals(|s| self.as_str(s, |s| fmt::Debug::fmt(s, f)))
420 }
421}
422
423impl fmt::Display for Symbol {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 with_session_globals(|s| self.as_str(s, |s| fmt::Display::fmt(s, f)))
426 }
427}
428
429pub struct SessionGlobals {
431 symbol_interner: Interner,
433 pub source_map: SourceMap,
435}
436
437impl Default for SessionGlobals {
438 fn default() -> Self {
439 Self { symbol_interner: Interner::prefilled(), source_map: SourceMap::default() }
440 }
441}
442
443scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
444
445#[inline]
447pub fn create_session_if_not_set_then<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
448 if !SESSION_GLOBALS.is_set() {
449 let sg = SessionGlobals::default();
450 SESSION_GLOBALS.set(&sg, || SESSION_GLOBALS.with(f))
451 } else {
452 SESSION_GLOBALS.with(f)
453 }
454}
455
456#[inline]
458pub fn with_session_globals<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
459 SESSION_GLOBALS.with(f)
460}
461
462#[derive(Eq)]
466enum InternedStr {
467 Static(&'static str),
469 Owned(Box<str>),
471}
472
473impl Borrow<str> for InternedStr {
474 fn borrow(&self) -> &str {
475 self.deref()
476 }
477}
478
479impl Deref for InternedStr {
480 type Target = str;
481
482 fn deref(&self) -> &Self::Target {
483 match self {
484 Self::Static(s) => s,
485 Self::Owned(s) => s,
486 }
487 }
488}
489
490impl PartialEq for InternedStr {
491 fn eq(&self, other: &InternedStr) -> bool {
492 self.deref() == other.deref()
493 }
494}
495
496impl Hash for InternedStr {
497 fn hash<H: Hasher>(&self, state: &mut H) {
498 self.deref().hash(state);
499 }
500}
501
502struct InnerInterner {
505 set: IndexSet<InternedStr, FxBuildHasher>,
509}
510
511struct Interner {
513 inner: RefCell<InnerInterner>,
514}
515
516impl Interner {
517 fn prefilled() -> Self {
519 Self::prefill(PRE_DEFINED)
520 }
521
522 fn prefill(init: &[&'static str]) -> Self {
524 let inner = InnerInterner {
525 set: init.iter().copied().map(InternedStr::Static).collect(),
527 };
528 Self { inner: RefCell::new(inner) }
529 }
530
531 fn intern(&self, string: &str) -> Symbol {
533 let InnerInterner { set } = &mut *self.inner.borrow_mut();
534
535 if let Some(sym) = set.get_index_of(string) {
536 return Symbol::new(sym as u32);
538 }
539
540 Symbol::new(set.insert_full(InternedStr::Owned(string.into())).0 as u32)
541 }
542
543 fn get<R>(&self, symbol: Symbol, with: impl FnOnce(&str) -> R) -> R {
545 let set = &self.inner.borrow().set;
546 with(set.get_index(symbol.as_u32() as usize).unwrap())
547 }
548}