gluon_base/
symbol.rs

1//! Module which contains types working with symbols
2use std::{
3    borrow::Borrow,
4    cmp::Ordering,
5    convert::TryFrom,
6    fmt,
7    hash::{BuildHasher, BuildHasherDefault, Hash, Hasher},
8    ops::Deref,
9    sync::Arc,
10};
11
12use crate::{
13    ast::{DisplayEnv, IdentEnv},
14    pos::{BytePos, Span},
15};
16
17// FIXME Don't have a double indirection (Arc + String)
18/// A symbol uniquely identifies something regardless of its name and which module it originated
19/// from
20#[derive(Clone, Eq, Default)]
21pub struct Symbol(Arc<SymbolInner>);
22
23#[derive(Debug, Default, Eq, PartialEq, Hash)]
24struct SymbolInner {
25    global: bool,
26    location: Option<u32>,
27    name: NameBuf,
28}
29
30#[derive(Debug, Default, Eq, PartialEq, Hash)]
31pub struct SymbolData<N = NameBuf> {
32    pub global: bool,
33    pub location: Option<(u32, u32)>,
34    pub name: N,
35}
36
37#[cfg(feature = "serde")]
38mod serialization {
39    use super::*;
40
41    use crate::serde::de::DeserializeState;
42    use crate::serde::ser::SerializeState;
43    use crate::serde::{Deserialize, Deserializer, Serialize, Serializer};
44    use crate::serialization::SeSeed;
45
46    impl<'de> Deserialize<'de> for Symbol {
47        fn deserialize<D>(deserializer: D) -> Result<Symbol, D::Error>
48        where
49            D: Deserializer<'de>,
50        {
51            use std::borrow::Cow;
52            Cow::<str>::deserialize(deserializer).map(|s| Symbol::from(&s[..]))
53        }
54    }
55
56    impl<'de, Id, T> DeserializeState<'de, crate::serialization::Seed<Id, T>> for Symbol {
57        fn deserialize_state<D>(
58            seed: &mut crate::serialization::Seed<Id, T>,
59            deserializer: D,
60        ) -> Result<Self, D::Error>
61        where
62            D: Deserializer<'de>,
63        {
64            use crate::serde::de::DeserializeSeed;
65            use crate::serialization::SharedSeed;
66
67            let seed = SharedSeed::new(seed);
68            seed.deserialize(deserializer)
69                .map(|s: String| Symbol::from(&s[..]))
70        }
71    }
72
73    impl Serialize for Symbol {
74        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75        where
76            S: Serializer,
77        {
78            serializer.collect_str(self)
79        }
80    }
81
82    impl SerializeState<SeSeed> for Symbol {
83        fn serialize_state<S>(&self, serializer: S, seed: &SeSeed) -> Result<S::Ok, S::Error>
84        where
85            S: Serializer,
86        {
87            {
88                crate::serialization::shared::serialize(self, serializer, seed)
89            }
90        }
91    }
92}
93
94impl Deref for Symbol {
95    type Target = SymbolRef;
96    fn deref(&self) -> &SymbolRef {
97        unsafe { &*(&*self.0.name.0 as *const str as *const SymbolRef) }
98    }
99}
100
101impl Borrow<SymbolRef> for Symbol {
102    fn borrow(&self) -> &SymbolRef {
103        &**self
104    }
105}
106
107impl AsRef<str> for Symbol {
108    fn as_ref(&self) -> &str {
109        self.as_pretty_str()
110    }
111}
112
113impl fmt::Debug for Symbol {
114    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115        write!(f, "{:?}", &**self)
116    }
117}
118
119impl fmt::Display for Symbol {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        write!(f, "{}", self.as_pretty_str())
122    }
123}
124
125impl PartialEq for Symbol {
126    fn eq(&self, other: &Symbol) -> bool {
127        **self == **other
128    }
129}
130
131impl PartialEq<SymbolRef> for Symbol {
132    fn eq(&self, other: &SymbolRef) -> bool {
133        **self == *other
134    }
135}
136
137impl PartialEq<Symbol> for SymbolRef {
138    fn eq(&self, other: &Symbol) -> bool {
139        *self == **other
140    }
141}
142
143impl PartialOrd for Symbol {
144    fn partial_cmp(&self, other: &Symbol) -> Option<Ordering> {
145        (**self).partial_cmp(other)
146    }
147}
148
149impl Ord for Symbol {
150    fn cmp(&self, other: &Symbol) -> Ordering {
151        (**self).cmp(other)
152    }
153}
154
155impl Hash for Symbol {
156    fn hash<H: Hasher>(&self, h: &mut H) {
157        (**self).hash(h)
158    }
159}
160
161impl From<String> for Symbol {
162    fn from(name: String) -> Symbol {
163        Symbol::from(&*name)
164    }
165}
166
167impl From<(Symbol, Span<BytePos>)> for Symbol {
168    fn from((name, _): (Symbol, Span<BytePos>)) -> Symbol {
169        name
170    }
171}
172
173impl<N> From<SymbolData<N>> for Symbol
174where
175    N: Into<NameBuf>,
176{
177    fn from(name: SymbolData<N>) -> Symbol {
178        Symbol(Arc::new(SymbolInner::new(name)))
179    }
180}
181
182impl From<&'_ str> for Symbol {
183    fn from(name: &str) -> Symbol {
184        Symbol(Arc::new(SymbolInner::new(SymbolData::<NameBuf>::from(
185            name,
186        ))))
187    }
188}
189
190impl<'a, N> From<&'a str> for SymbolData<N>
191where
192    N: From<&'a str>,
193{
194    fn from(mut name: &'a str) -> SymbolData<N> {
195        let global = name.starts_with('@');
196        let location = match name
197            .bytes()
198            .rposition(|b| (b < b'0' || b > b'9') && b != b'_')
199        {
200            Some(i) if i != 0 && name.as_bytes()[i] == b'@' => {
201                let loc = &name[(i + 1)..];
202                let mut iter = loc.split('_');
203                let line = iter.next();
204                let col = iter.next();
205                let opt = line
206                    .and_then(|line| line.parse::<u32>().ok())
207                    .and_then(|line| {
208                        col.and_then(|col| col.parse::<u32>().ok())
209                            .map(|col| (line, col))
210                    });
211
212                name = &name[..i];
213
214                opt
215            }
216            _ => None,
217        };
218
219        if global {
220            name = &name[1..];
221        }
222
223        SymbolData {
224            global,
225            location,
226            name: name.into(),
227        }
228    }
229}
230
231#[derive(Eq)]
232#[cfg_attr(feature = "serde_derive", derive(SerializeState))]
233#[cfg_attr(
234    feature = "serde_derive",
235    serde(serialize_state = "crate::serialization::SeSeed")
236)]
237pub struct SymbolRef(str);
238
239impl fmt::Debug for SymbolRef {
240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
241        write!(f, "{:p}:{}", self, &self.0)
242    }
243}
244
245impl fmt::Display for SymbolRef {
246    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247        write!(f, "{}", &self.0)
248    }
249}
250
251impl PartialEq for SymbolRef {
252    fn eq(&self, other: &SymbolRef) -> bool {
253        self.ptr() == other.ptr()
254    }
255}
256
257impl PartialOrd for SymbolRef {
258    fn partial_cmp(&self, other: &SymbolRef) -> Option<Ordering> {
259        self.ptr().partial_cmp(&other.ptr())
260    }
261}
262
263impl Ord for SymbolRef {
264    fn cmp(&self, other: &SymbolRef) -> Ordering {
265        self.ptr().cmp(&other.ptr())
266    }
267}
268
269impl Hash for SymbolRef {
270    fn hash<H: Hasher>(&self, h: &mut H) {
271        self.ptr().hash(h)
272    }
273}
274
275impl Symbol {
276    pub fn strong_count(sym: &Symbol) -> usize {
277        Arc::strong_count(&sym.0)
278    }
279
280    pub fn is_global(&self) -> bool {
281        self.0.global
282    }
283
284    pub fn is_primitive(&self) -> bool {
285        self.0.name.0.starts_with('#')
286    }
287
288    pub fn name_eq(&self, other: &Symbol) -> bool {
289        self.name() == other.name()
290    }
291
292    pub fn name(&self) -> &Name {
293        Name::new(self.as_pretty_str())
294    }
295
296    pub fn as_pretty_str(&self) -> &str {
297        &self.0.name.0[self.0.global as usize
298            ..self
299                .0
300                .location
301                .map_or_else(|| self.0.name.len(), |l| l as usize)]
302    }
303
304    pub fn as_data(&self) -> SymbolData<&Name> {
305        SymbolData::from(&self.0.name.0[..])
306    }
307}
308
309impl SymbolRef {
310    #[inline]
311    pub fn new<N: ?Sized + AsRef<str>>(n: &N) -> &SymbolRef {
312        unsafe { &*(Name::new(n) as *const Name as *const SymbolRef) }
313    }
314
315    /// Checks whether the names of two symbols are equal
316    pub fn name_eq(&self, other: &SymbolRef) -> bool {
317        self.name() == other.name()
318    }
319
320    pub fn is_global(&self) -> bool {
321        self.0.as_bytes().first() == Some(&b'@')
322    }
323
324    pub fn as_pretty_str(&self) -> &str {
325        let mut s = &self.0;
326        if let Some(b'@') = s.as_bytes().first() {
327            s = &s[1..];
328        }
329        Name::new(s).as_pretty_str()
330    }
331
332    pub fn as_str(&self) -> &str {
333        &self.0
334    }
335
336    pub fn name(&self) -> &Name {
337        Name::new(Name::new(&self.0).as_pretty_str())
338    }
339
340    pub fn raw_name(&self) -> &Name {
341        Name::new(&self.0)
342    }
343
344    /// Returns the name of this symbol as it was originally declared (strips location information
345    /// and module information)
346    pub fn declared_name(&self) -> &str {
347        self.name().declared_name()
348    }
349
350    pub fn definition_name(&self) -> &str {
351        Name::new(&self.0).definition_name()
352    }
353
354    fn ptr(&self) -> *const () {
355        self.0.as_bytes().as_ptr() as *const ()
356    }
357}
358
359#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
360#[cfg_attr(feature = "serde_derive", derive(DeserializeState))]
361#[cfg_attr(feature = "serde_derive", serde(deserialize_state = "S"))]
362#[cfg_attr(feature = "serde_derive", serde(de_parameters = "S"))]
363pub struct NameBuf(String);
364
365#[derive(Debug, Eq, Hash, Ord, PartialOrd)]
366pub struct Name(str);
367
368impl PartialEq for Name {
369    fn eq(&self, other: &Name) -> bool {
370        self.0.as_ptr() == other.0.as_ptr() || self.0 == other.0
371    }
372}
373
374impl ToOwned for Name {
375    type Owned = NameBuf;
376
377    fn to_owned(&self) -> NameBuf {
378        NameBuf::from(self)
379    }
380}
381
382pub struct Components<'a>(&'a str);
383
384impl<'a> Iterator for Components<'a> {
385    type Item = &'a str;
386
387    fn next(&mut self) -> Option<&'a str> {
388        if self.0.is_empty() {
389            None
390        } else {
391            Some(match self.0.find('.') {
392                Some(i) => {
393                    let (before, after) = self.0.split_at(i);
394                    self.0 = &after[1..];
395                    before
396                }
397                None => {
398                    let s = self.0;
399                    self.0 = "";
400                    s
401                }
402            })
403        }
404    }
405}
406
407impl<'a> From<&'a str> for &'a Name {
408    fn from(s: &'a str) -> &'a Name {
409        Name::new(s)
410    }
411}
412
413impl Name {
414    #[inline]
415    pub fn new<N: ?Sized + AsRef<str>>(n: &N) -> &Name {
416        unsafe { &*(n.as_ref() as *const str as *const Name) }
417    }
418
419    pub fn as_pretty_str(&self) -> &str {
420        Self::strip_position_suffix(&self.0)
421    }
422
423    pub fn len(&self) -> usize {
424        self.0.len()
425    }
426
427    pub fn as_str(&self) -> &str {
428        &self.0
429    }
430
431    pub fn components(&self) -> Components {
432        Components(&self.0)
433    }
434
435    pub fn module(&self) -> &Name {
436        let s = self.0.trim_end_matches(|c| c != '.');
437        Name::new(s.trim_end_matches('.'))
438    }
439
440    pub fn name(&self) -> &Name {
441        self.0
442            .rfind('.')
443            .map_or(self, |i| Name::new(&self.0[i + 1..]))
444    }
445
446    pub fn declared_name(&self) -> &str {
447        let name = self.definition_name();
448        name.rsplit('.').next().unwrap_or(name)
449    }
450
451    pub fn definition_name(&self) -> &str {
452        Self::strip_position_suffix(if self.0.as_bytes().get(0) == Some(&b'@') {
453            &self.0[1..]
454        } else {
455            &self.0
456        })
457    }
458
459    fn strip_position_suffix(name: &str) -> &str {
460        // Strip away a `:1234_56` suffix
461        let x = match name
462            .bytes()
463            .rposition(|b| (b < b'0' || b > b'9') && b != b'_')
464        {
465            Some(i) if name.as_bytes()[i] == b'@' => &name[..i],
466            _ => name,
467        };
468
469        x
470    }
471}
472
473impl NameBuf {
474    #[inline]
475    pub fn new<T>(name: T) -> NameBuf
476    where
477        T: Into<String>,
478    {
479        NameBuf(name.into())
480    }
481}
482
483impl fmt::Display for Name {
484    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
485        write!(f, "{}", &self.0)
486    }
487}
488
489impl fmt::Display for NameBuf {
490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
491        write!(f, "{}", self.0)
492    }
493}
494
495impl AsRef<Name> for str {
496    fn as_ref(&self) -> &Name {
497        Name::new(self)
498    }
499}
500impl AsRef<Name> for String {
501    fn as_ref(&self) -> &Name {
502        Name::new(self)
503    }
504}
505impl AsRef<Name> for Name {
506    fn as_ref(&self) -> &Name {
507        self
508    }
509}
510
511impl AsRef<str> for Name {
512    fn as_ref(&self) -> &str {
513        &self.0
514    }
515}
516
517impl AsRef<str> for NameBuf {
518    fn as_ref(&self) -> &str {
519        &*self.0
520    }
521}
522
523impl AsRef<Name> for NameBuf {
524    fn as_ref(&self) -> &Name {
525        self
526    }
527}
528
529impl Borrow<Name> for NameBuf {
530    fn borrow(&self) -> &Name {
531        self
532    }
533}
534
535impl Deref for NameBuf {
536    type Target = Name;
537    fn deref(&self) -> &Name {
538        Name::new(self)
539    }
540}
541
542impl<'a> From<&'a str> for NameBuf {
543    fn from(name: &'a str) -> NameBuf {
544        NameBuf(String::from(name))
545    }
546}
547
548impl From<String> for NameBuf {
549    fn from(name: String) -> NameBuf {
550        NameBuf(name)
551    }
552}
553
554impl From<NameBuf> for String {
555    fn from(name: NameBuf) -> String {
556        name.0
557    }
558}
559
560impl<'a> From<&'a Name> for NameBuf {
561    fn from(name: &'a Name) -> NameBuf {
562        NameBuf::from(&name.0)
563    }
564}
565
566impl SymbolInner {
567    fn new<N>(data: SymbolData<N>) -> SymbolInner
568    where
569        N: Into<NameBuf>,
570    {
571        let SymbolData {
572            global,
573            location,
574            name,
575        } = data;
576        let mut name: NameBuf = name.into();
577        if global {
578            name.0.insert(0, '@');
579        }
580        let inner_location = location.map(|(x, y)| {
581            let loc = u32::try_from(name.len()).unwrap();
582            use std::fmt::Write;
583            write!(name.0, "@{}_{}", x, y).unwrap();
584            loc
585        });
586
587        SymbolInner {
588            global,
589            location: inner_location,
590            name,
591        }
592    }
593}
594
595/// `Symbols` is a bidirectional mapping between `Symbol`s and their name as represented in a
596/// source file.
597/// Used to make identifiers within a single module point to the same symbol
598#[derive(Debug, Default)]
599pub struct Symbols {
600    indexes:
601        hashbrown::HashMap<SymbolData<&'static Name>, Symbol, BuildHasherDefault<fnv::FnvHasher>>,
602}
603
604impl Symbols {
605    pub fn new() -> Symbols {
606        Symbols {
607            indexes: Default::default(),
608        }
609    }
610
611    pub fn simple_symbol<N>(&mut self, name: N) -> Symbol
612    where
613        N: Into<NameBuf> + AsRef<Name>,
614    {
615        self.symbol(SymbolData {
616            global: false,
617            location: None,
618            name,
619        })
620    }
621
622    /// Looks up the symbol for `name` or creates a new symbol if it does not exist
623    pub fn symbol<N>(&mut self, name: SymbolData<N>) -> Symbol
624    where
625        N: Into<NameBuf> + AsRef<Name>,
626    {
627        let name_ref = SymbolData {
628            global: name.global,
629            location: name.location,
630            name: name.name.as_ref(),
631        };
632
633        let mut hasher = self.indexes.hasher().build_hasher();
634        name_ref.hash(&mut hasher);
635        let hash = hasher.finish();
636
637        match self
638            .indexes
639            .raw_entry_mut()
640            .from_hash(hash, |key| *key == name_ref)
641        {
642            hashbrown::hash_map::RawEntryMut::Occupied(entry) => entry.get().clone(),
643            hashbrown::hash_map::RawEntryMut::Vacant(entry) => {
644                let SymbolData {
645                    global,
646                    location,
647                    name,
648                } = name;
649                let mut name: NameBuf = name.into();
650                if global {
651                    name.0.insert(0, '@');
652                }
653                let inner_location = location.map(|(x, y)| {
654                    let loc = u32::try_from(name.len()).unwrap();
655                    use std::fmt::Write;
656                    write!(name.0, "@{}_{}", x, y).unwrap();
657                    loc
658                });
659
660                let key = unsafe { &*(name.definition_name() as *const str as *const Name) };
661                let s = Symbol(Arc::new(SymbolInner {
662                    global,
663                    location: inner_location,
664                    name,
665                }));
666                entry
667                    .insert_hashed_nocheck(
668                        hash,
669                        SymbolData {
670                            global,
671                            location,
672                            name: key,
673                        },
674                        s,
675                    )
676                    .1
677                    .clone()
678            }
679        }
680    }
681
682    pub fn contains_name<N>(&mut self, name: N) -> bool
683    where
684        N: AsRef<Name>,
685    {
686        let s = SymbolData::<&Name>::from(name.as_ref().as_str());
687        self.indexes.contains_key(&s)
688    }
689
690    pub fn len(&self) -> usize {
691        self.indexes.len()
692    }
693
694    pub fn is_empty(&self) -> bool {
695        self.indexes.is_empty()
696    }
697}
698
699/// `SymbolModule` wraps a `Symbols` struct and adds a prefix to all symbols created by the
700/// `symbol` method.
701/// While this prefix does not affect the uniques of a `Symbol` in any way, it does make the origin
702/// of a symbol clearer when pretty printing it
703#[derive(Debug)]
704pub struct SymbolModule<'a> {
705    symbols: &'a mut Symbols,
706    module: NameBuf,
707}
708
709impl<'a> SymbolModule<'a> {
710    pub fn new(module: String, symbols: &'a mut Symbols) -> SymbolModule<'a> {
711        SymbolModule {
712            symbols,
713            module: NameBuf(module),
714        }
715    }
716
717    pub fn simple_symbol<N>(&mut self, name: N) -> Symbol
718    where
719        N: Into<NameBuf> + AsRef<Name>,
720    {
721        self.symbols.simple_symbol(name)
722    }
723
724    /// Creates an unprefixed symbol, same as `Symbols::symbol`
725    pub fn symbol<N>(&mut self, name: SymbolData<N>) -> Symbol
726    where
727        N: Into<NameBuf> + AsRef<Name>,
728    {
729        self.symbols.symbol(name)
730    }
731
732    pub fn contains_name<N>(&mut self, name: N) -> bool
733    where
734        N: AsRef<Name>,
735    {
736        self.symbols.contains_name(name.as_ref())
737    }
738
739    /// Creates a symbol which is prefixed by the `module` argument passed in `new`
740    ///
741    /// ```
742    /// # use gluon_base::symbol::{Symbols, SymbolModule};
743    /// let mut symbols = Symbols::new();
744    /// let mut symbols = SymbolModule::new(String::from("test"), &mut symbols);
745    /// assert_eq!(symbols.simple_symbol("a").as_ref(), "a");
746    /// assert_eq!(symbols.scoped_symbol("a").as_ref(), "test.a");
747    /// ```
748    pub fn scoped_symbol(&mut self, name: &str) -> Symbol {
749        let len = self.module.0.len();
750        self.module.0.push('.');
751        self.module.0.push_str(name);
752        let symbol = self.symbols.symbol(SymbolData {
753            global: false,
754            location: None,
755            name: &*self.module,
756        });
757        self.module.0.truncate(len);
758        symbol
759    }
760
761    pub fn module(&self) -> &Name {
762        &self.module
763    }
764
765    pub fn len(&self) -> usize {
766        self.symbols.len()
767    }
768
769    pub fn is_empty(&self) -> bool {
770        self.symbols.is_empty()
771    }
772
773    pub fn symbols(&mut self) -> &mut Symbols {
774        self.symbols
775    }
776}
777
778impl DisplayEnv for Symbols {
779    type Ident = Symbol;
780
781    fn string<'a>(&'a self, ident: &'a Self::Ident) -> &'a str {
782        ident.as_ref()
783    }
784}
785
786impl IdentEnv for Symbols {
787    fn from_str(&mut self, s: &str) -> Symbol {
788        self.symbol(SymbolData::<&Name>::from(s))
789    }
790}
791
792impl<'s> DisplayEnv for SymbolModule<'s> {
793    type Ident = Symbol;
794
795    fn string<'a>(&'a self, ident: &'a Self::Ident) -> &'a str {
796        self.symbols.string(ident)
797    }
798}
799
800impl<'a> IdentEnv for SymbolModule<'a> {
801    fn from_str(&mut self, s: &str) -> Symbol {
802        self.symbol(SymbolData::<&Name>::from(s))
803    }
804}
805
806impl<P> From<crate::pos::Spanned<Symbol, P>> for Symbol {
807    fn from(s: crate::pos::Spanned<Symbol, P>) -> Self {
808        s.value
809    }
810}