diff options
Diffstat (limited to 'third_party/rust/jsparagus-ast/src/source_atom_set.rs')
-rw-r--r-- | third_party/rust/jsparagus-ast/src/source_atom_set.rs | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/third_party/rust/jsparagus-ast/src/source_atom_set.rs b/third_party/rust/jsparagus-ast/src/source_atom_set.rs new file mode 100644 index 0000000000..25369c9777 --- /dev/null +++ b/third_party/rust/jsparagus-ast/src/source_atom_set.rs @@ -0,0 +1,221 @@ +use indexmap::set::IndexSet; + +/// Index into SourceAtomSet.atoms. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct SourceAtomSetIndex { + index: usize, +} +impl SourceAtomSetIndex { + fn new(index: usize) -> Self { + Self { index } + } +} + +impl From<SourceAtomSetIndex> for usize { + fn from(index: SourceAtomSetIndex) -> usize { + index.index + } +} + +// Call $handler macro with the list of common atoms. +// +// Basic Usage: +// +// ``` +// for_all_common_atoms!(test); +// ``` +// +// is expanded to +// +// ``` +// test!( +// ("arguments", arguments, Arguments), +// ("async", async_, Async), +// ... +// ); +// ``` +// +// Extra Parameters: +// +// ``` +// for_all_common_atoms!(test, foo, bar); +// ``` +// +// is expanded to +// +// ``` +// test!( +// foo, bar, +// ("arguments", arguments, Arguments), +// ("async", async_, Async), +// ... +// ); +// ``` +macro_rules! for_all_common_atoms { + ($handler:ident $(, $($params:tt)*)?) => { + // string representation, method name, enum variant + $handler!( + $($($params)*,)? + ("arguments", arguments, Arguments), + ("as", as_, As), + ("async", async_, Async), + ("await", await_, Await), + ("break", break_, Break), + ("case", case, Case), + ("catch", catch, Catch), + ("class", class, Class), + ("const", const_, Const), + ("continue", continue_, Continue), + ("debugger", debugger, Debugger), + ("default", default, Default), + ("delete", delete, Delete), + ("do", do_, Do), + ("else", else_, Else), + ("enum", enum_, Enum), + ("eval", eval, Eval), + ("export", export, Export), + ("extends", extends, Extends), + ("false", false_, False), + ("finally", finally, Finally), + ("for", for_, For), + ("from", from, From), + ("function", function, Function), + ("get", get, Get), + ("if", if_, If), + ("implements", implements, Implements), + ("import", import, Import), + ("in", in_, In), + ("instanceof", instanceof, Instanceof), + ("interface", interface, Interface), + ("let", let_, Let), + ("new", new_, New), + ("null", null, Null), + ("of", of, Of), + ("package", package, Package), + ("private", private, Private), + ("protected", protected, Protected), + ("public", public, Public), + ("return", return_, Return), + ("set", set, Set), + ("static", static_, Static), + ("super", super_, Super), + ("switch", switch, Switch), + ("target", target, Target), + ("this", this, This), + ("throw", throw, Throw), + ("true", true_, True), + ("try", try_, Try), + ("typeof", typeof_, Typeof), + ("var", var, Var), + ("void", void, Void), + ("while", while_, While), + ("with", with, With), + ("yield", yield_, Yield), + ("use strict", use_strict, UseStrict), + ("__proto__", __proto__, Proto), + ); + } +} + +// Define CommonAtoms enum, with +// +// enum CommonAtoms { +// Arguments = 0, +// Async, +// ... +// } +macro_rules! define_enum { + (($s0:tt, $method0:ident, $variant0:ident), + $(($s:tt, $method:ident, $variant:ident),)*) => { + enum CommonAtoms { + $variant0 = 0, + $($variant,)* + } + }; +} +for_all_common_atoms!(define_enum); + +// Define CommonSourceAtomSetIndices struct. +// +// impl CommonSourceAtomSetIndices { +// pub fn arguments() -> SourceAtomSetIndex { ... } +// pub fn async_() -> SourceAtomSetIndex { ... } +// ... +// } +macro_rules! define_struct { + ($(($s:tt, $method:ident, $variant:ident),)*) => { + #[derive(Debug)] + pub struct CommonSourceAtomSetIndices {} + + impl CommonSourceAtomSetIndices { + $( + pub fn $method() -> SourceAtomSetIndex { + SourceAtomSetIndex::new(CommonAtoms::$variant as usize) + } + )* + } + }; +} +for_all_common_atoms!(define_struct); + +/// Set of atoms, including the following: +/// +/// * atoms referred from bytecode +/// * variable names referred from scope data +/// +/// WARNING: This set itself does *NOT* map to JSScript::atoms(). +#[derive(Debug)] +pub struct SourceAtomSet<'alloc> { + atoms: IndexSet<&'alloc str>, +} + +impl<'alloc> SourceAtomSet<'alloc> { + // Create a set, with all common atoms inserted. + pub fn new() -> Self { + let mut result = Self { + atoms: IndexSet::new(), + }; + result.insert_common_atoms(); + result + } + + // Insert all common atoms. + fn insert_common_atoms(&mut self) { + macro_rules! insert_atom { + ($self: ident, + $(($s:tt, $method:ident, $variant:ident),)*) => { + $( + $self.atoms.insert($s); + )* + }; + } + for_all_common_atoms!(insert_atom, self); + } + + // Create a set, without any common atoms. + // + // This is for moving `SourceAtomSet` out of `Rc<RefCell>`, by replacing + // it with the result of this method. + pub fn new_uninitialized() -> Self { + Self { + // 256 is a number which should cover 75% of scripts without + // reallocation. + atoms: IndexSet::with_capacity(256), + } + } + + pub fn insert(&mut self, s: &'alloc str) -> SourceAtomSetIndex { + let (index, _) = self.atoms.insert_full(s); + SourceAtomSetIndex::new(index) + } + + pub fn get(&self, index: SourceAtomSetIndex) -> &'alloc str { + self.atoms.get_index(usize::from(index)).unwrap() + } +} + +impl<'alloc> From<SourceAtomSet<'alloc>> for Vec<&'alloc str> { + fn from(set: SourceAtomSet<'alloc>) -> Vec<&'alloc str> { + set.atoms.into_iter().collect() + } +} |