1 //! Types dealing with the substitutions table. 2 3 use super::DemangleWrite; 4 use ast; 5 use std::fmt; 6 use std::iter::FromIterator; 7 use std::ops::Deref; 8 use vec::Vec; 9 10 /// An enumeration of all of the types that can end up in the substitution 11 /// table. 12 #[doc(hidden)] 13 #[derive(Clone, Debug, PartialEq, Eq)] 14 #[allow(clippy::large_enum_variant)] 15 pub enum Substitutable { 16 /// An `<unscoped-template-name>` production. 17 UnscopedTemplateName(ast::UnscopedTemplateName), 18 19 /// A `<type>` production. 20 Type(ast::Type), 21 22 /// A `<template-template-param>` production. 23 TemplateTemplateParam(ast::TemplateTemplateParam), 24 25 /// An `<unresolved-type>` production. 26 UnresolvedType(ast::UnresolvedType), 27 28 /// A `<prefix>` production. 29 Prefix(ast::Prefix), 30 } 31 32 impl<'subs, W> ast::Demangle<'subs, W> for Substitutable 33 where 34 W: 'subs + DemangleWrite, 35 { demangle<'prev, 'ctx>( &'subs self, ctx: &'ctx mut ast::DemangleContext<'subs, W>, scope: Option<ast::ArgScopeStack<'prev, 'subs>>, ) -> fmt::Result36 fn demangle<'prev, 'ctx>( 37 &'subs self, 38 ctx: &'ctx mut ast::DemangleContext<'subs, W>, 39 scope: Option<ast::ArgScopeStack<'prev, 'subs>>, 40 ) -> fmt::Result { 41 match *self { 42 Substitutable::UnscopedTemplateName(ref name) => name.demangle(ctx, scope), 43 Substitutable::Type(ref ty) => ty.demangle(ctx, scope), 44 Substitutable::TemplateTemplateParam(ref ttp) => ttp.demangle(ctx, scope), 45 Substitutable::UnresolvedType(ref ty) => ty.demangle(ctx, scope), 46 Substitutable::Prefix(ref prefix) => prefix.demangle(ctx, scope), 47 } 48 } 49 } 50 51 impl<'a> ast::GetLeafName<'a> for Substitutable { get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<ast::LeafName<'a>>52 fn get_leaf_name(&'a self, subs: &'a SubstitutionTable) -> Option<ast::LeafName<'a>> { 53 match *self { 54 Substitutable::UnscopedTemplateName(ref name) => name.get_leaf_name(subs), 55 Substitutable::Prefix(ref prefix) => prefix.get_leaf_name(subs), 56 Substitutable::Type(ref ty) => ty.get_leaf_name(subs), 57 _ => None, 58 } 59 } 60 } 61 62 impl ast::IsCtorDtorConversion for Substitutable { is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool63 fn is_ctor_dtor_conversion(&self, subs: &SubstitutionTable) -> bool { 64 match *self { 65 Substitutable::Prefix(ref prefix) => prefix.is_ctor_dtor_conversion(subs), 66 _ => false, 67 } 68 } 69 } 70 71 /// The table of substitutable components that we have parsed thus far, and for 72 /// which there are potential back-references. 73 #[doc(hidden)] 74 #[derive(Clone, Default, PartialEq, Eq)] 75 pub struct SubstitutionTable { 76 substitutions: Vec<Substitutable>, 77 // There are components which are typically candidates for substitution, but 78 // in some particular circumstances are not. Instances of such components 79 // which are not candidates for substitution end up in this part of the 80 // table. See `<prefix>` parsing for further details. 81 non_substitutions: Vec<Substitutable>, 82 } 83 84 impl fmt::Debug for SubstitutionTable { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 86 f.pad("SubstitutionTable ")?; 87 f.debug_map() 88 .entries(self.substitutions.iter().enumerate()) 89 .finish()?; 90 f.pad("non_substitutions ")?; 91 f.debug_map() 92 .entries(self.non_substitutions.iter().enumerate()) 93 .finish() 94 } 95 } 96 97 impl SubstitutionTable { 98 /// Construct a new `SubstitutionTable`. new() -> SubstitutionTable99 pub fn new() -> SubstitutionTable { 100 Default::default() 101 } 102 103 /// Insert a freshly-parsed substitutable component into the table and 104 /// return the index at which it now lives. insert(&mut self, entity: Substitutable) -> usize105 pub fn insert(&mut self, entity: Substitutable) -> usize { 106 let idx = self.substitutions.len(); 107 log!("SubstitutionTable::insert @ {}: {:?}", idx, entity); 108 self.substitutions.push(entity); 109 idx 110 } 111 112 /// Insert a an entity into the table that is not a candidate for 113 /// substitution. insert_non_substitution(&mut self, entity: Substitutable) -> usize114 pub fn insert_non_substitution(&mut self, entity: Substitutable) -> usize { 115 let idx = self.non_substitutions.len(); 116 self.non_substitutions.push(entity); 117 idx 118 } 119 120 /// Does this substitution table contain a component at the given index? contains(&self, idx: usize) -> bool121 pub fn contains(&self, idx: usize) -> bool { 122 idx < self.substitutions.len() 123 } 124 125 /// Get the type referenced by the given handle, or None if there is no such 126 /// entry, or there is an entry that is not a type. get_type(&self, handle: &ast::TypeHandle) -> Option<&ast::Type>127 pub fn get_type(&self, handle: &ast::TypeHandle) -> Option<&ast::Type> { 128 if let ast::TypeHandle::BackReference(idx) = *handle { 129 self.substitutions.get(idx).and_then(|s| match *s { 130 Substitutable::Type(ref ty) => Some(ty), 131 _ => None, 132 }) 133 } else { 134 None 135 } 136 } 137 138 /// Remove the last entry from the substitutions table and return it, or 139 /// `None` if the table is empty. pop(&mut self) -> Option<Substitutable>140 pub fn pop(&mut self) -> Option<Substitutable> { 141 log!("SubstitutionTable::pop @ {}: {:?}", self.len(), self.last()); 142 self.substitutions.pop() 143 } 144 145 /// Get the `idx`th entity that is not a candidate for substitution. Panics 146 /// if `idx` is out of bounds. non_substitution(&self, idx: usize) -> &Substitutable147 pub fn non_substitution(&self, idx: usize) -> &Substitutable { 148 &self.non_substitutions[idx] 149 } 150 151 /// Get the `idx`th entity that is not a candidate for substitution. Returns 152 /// `None` if `idx` is out of bounds. get_non_substitution(&self, idx: usize) -> Option<&Substitutable>153 pub fn get_non_substitution(&self, idx: usize) -> Option<&Substitutable> { 154 self.non_substitutions.get(idx) 155 } 156 } 157 158 impl FromIterator<Substitutable> for SubstitutionTable { from_iter<I: IntoIterator<Item = Substitutable>>(iter: I) -> Self159 fn from_iter<I: IntoIterator<Item = Substitutable>>(iter: I) -> Self { 160 SubstitutionTable { 161 substitutions: Vec::from_iter(iter), 162 non_substitutions: vec![], 163 } 164 } 165 } 166 167 impl Deref for SubstitutionTable { 168 type Target = [Substitutable]; 169 deref(&self) -> &Self::Target170 fn deref(&self) -> &Self::Target { 171 &self.substitutions[..] 172 } 173 } 174