1 use indexmap::set::IndexSet; 2 3 /// Index into SourceAtomSet.atoms. 4 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 5 pub struct SourceAtomSetIndex { 6 index: usize, 7 } 8 impl SourceAtomSetIndex { new(index: usize) -> Self9 fn new(index: usize) -> Self { 10 Self { index } 11 } 12 } 13 14 impl From<SourceAtomSetIndex> for usize { from(index: SourceAtomSetIndex) -> usize15 fn from(index: SourceAtomSetIndex) -> usize { 16 index.index 17 } 18 } 19 20 // Call $handler macro with the list of common atoms. 21 // 22 // Basic Usage: 23 // 24 // ``` 25 // for_all_common_atoms!(test); 26 // ``` 27 // 28 // is expanded to 29 // 30 // ``` 31 // test!( 32 // ("arguments", arguments, Arguments), 33 // ("async", async_, Async), 34 // ... 35 // ); 36 // ``` 37 // 38 // Extra Parameters: 39 // 40 // ``` 41 // for_all_common_atoms!(test, foo, bar); 42 // ``` 43 // 44 // is expanded to 45 // 46 // ``` 47 // test!( 48 // foo, bar, 49 // ("arguments", arguments, Arguments), 50 // ("async", async_, Async), 51 // ... 52 // ); 53 // ``` 54 macro_rules! for_all_common_atoms { 55 ($handler:ident $(, $($params:tt)*)?) => { 56 // string representation, method name, enum variant 57 $handler!( 58 $($($params)*,)? 59 ("arguments", arguments, Arguments), 60 ("as", as_, As), 61 ("async", async_, Async), 62 ("await", await_, Await), 63 ("break", break_, Break), 64 ("case", case, Case), 65 ("catch", catch, Catch), 66 ("class", class, Class), 67 ("const", const_, Const), 68 ("continue", continue_, Continue), 69 ("debugger", debugger, Debugger), 70 ("default", default, Default), 71 ("delete", delete, Delete), 72 ("do", do_, Do), 73 ("else", else_, Else), 74 ("enum", enum_, Enum), 75 ("eval", eval, Eval), 76 ("export", export, Export), 77 ("extends", extends, Extends), 78 ("false", false_, False), 79 ("finally", finally, Finally), 80 ("for", for_, For), 81 ("from", from, From), 82 ("function", function, Function), 83 ("get", get, Get), 84 ("if", if_, If), 85 ("implements", implements, Implements), 86 ("import", import, Import), 87 ("in", in_, In), 88 ("instanceof", instanceof, Instanceof), 89 ("interface", interface, Interface), 90 ("let", let_, Let), 91 ("new", new_, New), 92 ("null", null, Null), 93 ("of", of, Of), 94 ("package", package, Package), 95 ("private", private, Private), 96 ("protected", protected, Protected), 97 ("public", public, Public), 98 ("return", return_, Return), 99 ("set", set, Set), 100 ("static", static_, Static), 101 ("super", super_, Super), 102 ("switch", switch, Switch), 103 ("target", target, Target), 104 ("this", this, This), 105 ("throw", throw, Throw), 106 ("true", true_, True), 107 ("try", try_, Try), 108 ("typeof", typeof_, Typeof), 109 ("var", var, Var), 110 ("void", void, Void), 111 ("while", while_, While), 112 ("with", with, With), 113 ("yield", yield_, Yield), 114 ("use strict", use_strict, UseStrict), 115 ("__proto__", __proto__, Proto), 116 ); 117 } 118 } 119 120 // Define CommonAtoms enum, with 121 // 122 // enum CommonAtoms { 123 // Arguments = 0, 124 // Async, 125 // ... 126 // } 127 macro_rules! define_enum { 128 (($s0:tt, $method0:ident, $variant0:ident), 129 $(($s:tt, $method:ident, $variant:ident),)*) => { 130 enum CommonAtoms { 131 $variant0 = 0, 132 $($variant,)* 133 } 134 }; 135 } 136 for_all_common_atoms!(define_enum); 137 138 // Define CommonSourceAtomSetIndices struct. 139 // 140 // impl CommonSourceAtomSetIndices { 141 // pub fn arguments() -> SourceAtomSetIndex { ... } 142 // pub fn async_() -> SourceAtomSetIndex { ... } 143 // ... 144 // } 145 macro_rules! define_struct { 146 ($(($s:tt, $method:ident, $variant:ident),)*) => { 147 #[derive(Debug)] 148 pub struct CommonSourceAtomSetIndices {} 149 150 impl CommonSourceAtomSetIndices { 151 $( 152 pub fn $method() -> SourceAtomSetIndex { 153 SourceAtomSetIndex::new(CommonAtoms::$variant as usize) 154 } 155 )* 156 } 157 }; 158 } 159 for_all_common_atoms!(define_struct); 160 161 /// Set of atoms, including the following: 162 /// 163 /// * atoms referred from bytecode 164 /// * variable names referred from scope data 165 /// 166 /// WARNING: This set itself does *NOT* map to JSScript::atoms(). 167 #[derive(Debug)] 168 pub struct SourceAtomSet<'alloc> { 169 atoms: IndexSet<&'alloc str>, 170 } 171 172 impl<'alloc> SourceAtomSet<'alloc> { 173 // Create a set, with all common atoms inserted. new() -> Self174 pub fn new() -> Self { 175 let mut result = Self { 176 atoms: IndexSet::new(), 177 }; 178 result.insert_common_atoms(); 179 result 180 } 181 182 // Insert all common atoms. insert_common_atoms(&mut self)183 fn insert_common_atoms(&mut self) { 184 macro_rules! insert_atom { 185 ($self: ident, 186 $(($s:tt, $method:ident, $variant:ident),)*) => { 187 $( 188 $self.atoms.insert($s); 189 )* 190 }; 191 } 192 for_all_common_atoms!(insert_atom, self); 193 } 194 195 // Create a set, without any common atoms. 196 // 197 // This is for moving `SourceAtomSet` out of `Rc<RefCell>`, by replacing 198 // it with the result of this method. new_uninitialized() -> Self199 pub fn new_uninitialized() -> Self { 200 Self { 201 // 256 is a number which should cover 75% of scripts without 202 // reallocation. 203 atoms: IndexSet::with_capacity(256), 204 } 205 } 206 insert(&mut self, s: &'alloc str) -> SourceAtomSetIndex207 pub fn insert(&mut self, s: &'alloc str) -> SourceAtomSetIndex { 208 let (index, _) = self.atoms.insert_full(s); 209 SourceAtomSetIndex::new(index) 210 } 211 get(&self, index: SourceAtomSetIndex) -> &'alloc str212 pub fn get(&self, index: SourceAtomSetIndex) -> &'alloc str { 213 self.atoms.get_index(usize::from(index)).unwrap() 214 } 215 } 216 217 impl<'alloc> From<SourceAtomSet<'alloc>> for Vec<&'alloc str> { from(set: SourceAtomSet<'alloc>) -> Vec<&'alloc str>218 fn from(set: SourceAtomSet<'alloc>) -> Vec<&'alloc str> { 219 set.atoms.into_iter().collect() 220 } 221 } 222