diff --git a/Cargo.toml b/Cargo.toml index e5a82c7..476cd62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "resast" -version = "0.5.0" -authors = ["rfm "] +version = "0.6.0-alpha.1" +authors = ["rfm "] edition = "2018" description = "Rusty-ECMAScript Abstract Syntax Tree" -repository = "https://github.com/FreeMasen/resast" +repository = "https://github.com/rusty-ecma/resast" license = "MIT" keywords = ["JavaScript", "parsing", "JS", "ES", "ECMA"] categories = ["parsing", "text-processing", "web-programming"] diff --git a/README.md b/README.md index 232f47b..b351253 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # RESAST + > Rusty ECMAScript Abstract Syntax Tree [![crates.io](https://img.shields.io/crates/v/resast.svg)](https://crates.io/crates/resast) [![API Documentation on docs.rs](https://docs.rs/resast/badge.svg)](https://docs.rs/resast) -[![last commit master](https://img.shields.io/github/last-commit/FreeMasen/resast.svg)](https://github.com/FreeMasen/resast/) +[![last commit main](https://img.shields.io/github/last-commit/FreeMasen/resast.svg)](https://github.com/FreeMasen/resast/) ## Contributing + If you are interested in contributing to RESAST know that I would be happy for the help! Feel free to open issues and/or pull requests for anything that you see that might be an improvement. @@ -15,4 +17,4 @@ I do not work on this full time, please be patient if I am not able to respond q Before starting on any work, please comment on an existing issue or open a new issue in order to reduce the chance that work would get duplicated. -[check out the issues](https://github.com/FreeMasen/resast/issues) \ No newline at end of file +[check out the issues](https://github.com/FreeMasen/resast/issues) diff --git a/src/decl.rs b/src/decl.rs index dd39377..30b6f49 100644 --- a/src/decl.rs +++ b/src/decl.rs @@ -10,35 +10,35 @@ use crate::{Class, Func, Ident}; derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum Decl<'a> { +pub enum Decl { /// A variable declaration /// ```js /// var x, b; /// let y, a = 0; /// const q = 100 /// ``` - Var(VarKind, Vec>), + Var(VarKind, Vec>), /// A function declaration /// ```js /// function thing() {} /// ``` - Func(Func<'a>), + Func(Func), /// A class declaration /// ```js /// class Thing {} /// ``` - Class(Class<'a>), + Class(Class), /// An import declaration /// ```js /// import * as moment from 'moment'; /// import Thing, {thing} from 'stuff'; /// ``` - Import(Box>), + Import(Box>), /// An export declaration /// ```js /// export function thing() {} /// ``` - Export(Box>), + Export(Box>), } /// The identifier and optional value of a variable declaration @@ -48,19 +48,9 @@ pub enum Decl<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct VarDecl<'a> { - pub id: Pat<'a>, - pub init: Option>, -} - -/// A module declaration, This would only be available -/// in an ES Mod, it would be either an import or -/// export at the top level -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub enum ModDecl<'a> { - Import(ModImport<'a>), - Export(ModExport<'a>), +pub struct VarDecl { + pub id: Pat, + pub init: Option>, } /// A declaration that imports exported @@ -71,9 +61,9 @@ pub enum ModDecl<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ModImport<'a> { - pub specifiers: Vec>, - pub source: Lit<'a>, +pub struct ModImport { + pub specifiers: Vec>, + pub source: Lit, } /// The name of the thing being imported @@ -83,7 +73,7 @@ pub struct ModImport<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum ImportSpecifier<'a> { +pub enum ImportSpecifier { /// A specifier in curly braces, this might /// have a local alias /// @@ -91,27 +81,27 @@ pub enum ImportSpecifier<'a> { /// import {Thing} from './stuff.js'; /// import {People as Persons} from './places.js'; /// ``` - Normal(Vec>), + Normal(Vec>), /// A specifier that has been exported with the /// default keyword, this should not be wrapped in /// curly braces. /// ```js /// import DefaultThing from './stuff/js'; /// ``` - Default(Ident<'a>), + Default(Ident), /// Import all exported members from a module /// in a namespace. /// /// ```js /// import * as Moment from 'moment.js'; /// ``` - Namespace(Ident<'a>), + Namespace(Ident), } #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct NormalImportSpec<'a> { - pub local: Ident<'a>, - pub imported: Ident<'a>, +pub struct NormalImportSpec { + pub alias: Option>, + pub imported: Ident, } /// Something exported from this module @@ -121,13 +111,13 @@ pub struct NormalImportSpec<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum ModExport<'a> { +pub enum ModExport { /// ```js /// export default function() {}; /// //or /// export default 1; /// ``` - Default(DefaultExportDecl<'a>), + Default(DefaultExportDecl), ///```js /// export {foo} from 'mod'; /// //or @@ -138,30 +128,25 @@ pub enum ModExport<'a> { /// export function bar() { /// } /// ``` - Named(NamedExportDecl<'a>), + Named(NamedExportDecl), /// ```js /// export * from 'mod'; /// ``` All { - alias: Option>, - name: Lit<'a>, + alias: Option>, + name: Lit, }, } -// pub struct NamedExportDecl<'a> { -// decl: Option>>, -// specs: Vec>, -// source: Option> -// } /// An export that has a name /// ```js /// export function thing() {} /// export {stuff} from 'place'; #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub enum NamedExportDecl<'a> { - Decl(Decl<'a>), - Specifier(Vec>, Option>), +pub enum NamedExportDecl { + Decl(Decl), + Specifier(Vec>, Option>), } /// A default export @@ -174,9 +159,9 @@ pub enum NamedExportDecl<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum DefaultExportDecl<'a> { - Decl(Decl<'a>), - Expr(Expr<'a>), +pub enum DefaultExportDecl { + Decl(Decl), + Expr(Expr), } /// The name of the thing being exported @@ -193,7 +178,7 @@ pub enum DefaultExportDecl<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct ExportSpecifier<'a> { - pub local: Ident<'a>, - pub exported: Ident<'a>, +pub struct ExportSpecifier { + pub local: Ident, + pub alias: Option>, } diff --git a/src/expr.rs b/src/expr.rs index f1d0d2c..6dc3d41 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,455 +1,480 @@ -use crate::pat::Pat; -use crate::{AssignOp, BinaryOp, LogicalOp, PropKind, UnaryOp, UpdateOp}; -use crate::{Class, Func, FuncArg, FuncBody, Ident}; -use std::borrow::Cow; -/// A slightly more granular program part that a statement -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr( - all(feature = "serde", not(feature = "esprima")), - derive(Deserialize, Serialize) -)] -#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum Expr<'a> { - /// `[0,,]` - Array(ArrayExpr<'a>), - /// An arrow function - /// ```js - /// () => console.log(); - /// x => { - /// return x; - /// } - /// ``` - ArrowFunc(ArrowFuncExpr<'a>), - /// Used for resolving possible sequence expressions - /// that are arrow parameters - ArrowParamPlaceHolder(Vec>, bool), - /// Assignment or update assignment - /// ```js - /// a = 0 - /// b += 1 - /// ``` - Assign(AssignExpr<'a>), - /// The `await` keyword followed by another `Expr` - Await(Box>), - /// An operation that has two arguments - Binary(BinaryExpr<'a>), - /// A class expression see `Class` - Class(Class<'a>), - /// Calling a function or method - Call(CallExpr<'a>), - /// A ternery expression - Conditional(ConditionalExpr<'a>), - /// see `Function` - Func(Func<'a>), - /// An identifier - Ident(Ident<'a>), - /// A literal value, see `Literal` - Lit(Lit<'a>), - /// A specialized `BinaryExpr` for logical evaluation - /// ```js - /// true && true - /// false || true - /// ``` - Logical(LogicalExpr<'a>), - /// Accessing the member of a value - /// ```js - /// b['thing']; - /// c.stuff; - /// ``` - Member(MemberExpr<'a>), - /// currently just `new.target` - MetaProp(MetaProp<'a>), - /// ```js - /// var a = true ? 'stuff' : 'things'; - /// ``` - /// `{}` - /// Calling a constructor - New(NewExpr<'a>), - Obj(ObjExpr<'a>), - /// Any sequence of expressions separated with a comma - Sequence(SequenceExpr<'a>), - /// `...` followed by an `Expr` - Spread(Box>), - /// `super` - Super, - /// A template literal preceded by a tag function identifier - TaggedTemplate(TaggedTemplateExpr<'a>), - /// `this` - This, - /// An operation that has one argument - /// ```js - /// typeof 'a'; - /// +9; - /// ``` - Unary(UnaryExpr<'a>), - /// Increment or decrement - /// ```js - /// 1++ - /// --2 - /// ``` - Update(UpdateExpr<'a>), - /// yield a value from inside of a generator function - Yield(YieldExpr<'a>), -} - -impl<'a> Expr<'a> { - pub fn ident_from(s: &'a str) -> Self { - Expr::Ident(Ident::from(s)) - } -} - -/// `[a, b, c]` -pub type ArrayExpr<'a> = Vec>>; -/// `{a: 'b', c, ...d}` -pub type ObjExpr<'a> = Vec>; -/// A single part of an object literal -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum ObjProp<'a> { - Prop(Prop<'a>), - Spread(Expr<'a>), -} - -/// A single part of an object literal or class -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr( - all(feature = "serde", not(feature = "esprima")), - derive(Deserialize, Serialize) -)] -#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct Prop<'a> { - pub key: PropKey<'a>, - pub value: PropValue<'a>, - pub kind: PropKind, - pub method: bool, - pub computed: bool, - pub short_hand: bool, - pub is_static: bool, -} - -/// An object literal or class property identifier -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum PropKey<'a> { - Lit(Lit<'a>), - Expr(Expr<'a>), - Pat(Pat<'a>), -} - -/// The value of an object literal or class property -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum PropValue<'a> { - Expr(Expr<'a>), - Pat(Pat<'a>), - None, -} - -/// An operation that takes one argument -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct UnaryExpr<'a> { - pub operator: UnaryOp, - pub prefix: bool, - pub argument: Box>, -} - -/// Increment or decrementing a value -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct UpdateExpr<'a> { - pub operator: UpdateOp, - pub argument: Box>, - pub prefix: bool, -} - -/// An operation that requires 2 arguments -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct BinaryExpr<'a> { - pub operator: BinaryOp, - pub left: Box>, - pub right: Box>, -} - -/// An assignment or update + assignment operation -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct AssignExpr<'a> { - pub operator: AssignOp, - pub left: AssignLeft<'a>, - pub right: Box>, -} - -/// The value being assigned to -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum AssignLeft<'a> { - Pat(Pat<'a>), - Expr(Box>), -} - -/// A specialized `BinaryExpr` for logical evaluation -/// ```js -/// true && true -/// false || true -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct LogicalExpr<'a> { - pub operator: LogicalOp, - pub left: Box>, - pub right: Box>, -} - -/// Accessing the member of a value -/// ```js -/// b['thing']; -/// c.stuff; -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct MemberExpr<'a> { - pub object: Box>, - pub property: Box>, - pub computed: bool, -} - -/// A ternery expression -/// ```js -/// var a = true ? 'stuff' : 'things'; -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ConditionalExpr<'a> { - pub test: Box>, - pub alternate: Box>, - pub consequent: Box>, -} - -/// Calling a function or method -/// ```js -/// Math.random() -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct CallExpr<'a> { - pub callee: Box>, - pub arguments: Vec>, -} - -/// Calling a constructor -/// ```js -/// new Uint8Array(32); -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct NewExpr<'a> { - pub callee: Box>, - pub arguments: Vec>, -} - -/// A collection of `Exprs` separated by commas -pub type SequenceExpr<'a> = Vec>; - -/// An arrow function -/// ```js -/// let x = () => y; -/// let q = x => { -/// return x + 1; -/// } -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ArrowFuncExpr<'a> { - pub id: Option>, - pub params: Vec>, - pub body: ArrowFuncBody<'a>, - pub expression: bool, - pub generator: bool, - pub is_async: bool, -} - -/// The body portion of an arrow function can be either an expression or a block of statements -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub enum ArrowFuncBody<'a> { - FuncBody(FuncBody<'a>), - Expr(Box>), -} - -/// yield a value from inside of a generator function -/// ```js -/// function *gen() { -/// while ((new Date() / 1000) < Number.MAX_VALUE) { -/// yield new Date() / 1000; -/// } -/// } -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct YieldExpr<'a> { - pub argument: Option>>, - pub delegate: bool, -} - -/// A Template literal preceded by a function identifier -/// see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) for more details -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct TaggedTemplateExpr<'a> { - pub tag: Box>, - pub quasi: TemplateLit<'a>, -} - -/// A template string literal -/// ```js -/// `I own ${0} birds`; -/// ``` -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr( - all(feature = "serde", not(feature = "esprima")), - derive(Deserialize, Serialize) -)] -#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct TemplateLit<'a> { - pub quasis: Vec>, - pub expressions: Vec>, -} - -/// The text part of a `TemplateLiteral` -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr( - all(feature = "serde", not(feature = "esprima")), - derive(Deserialize, Serialize) -)] -#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct TemplateElement<'a> { - pub tail: bool, - /// The non-quoted version - pub cooked: Cow<'a, str>, - /// The quoted version - pub raw: Cow<'a, str>, -} - -impl<'a> TemplateElement<'a> { - pub fn from(tail: bool, cooked: &'a str, raw: &'a str) -> TemplateElement<'a> { - Self { - tail, - cooked: Cow::Borrowed(cooked), - raw: Cow::Borrowed(raw), - } - } -} - -/// pretty much just `new.target` -/// ```js -/// function Thing(one, two) { -/// if (!new.target) { -/// return new Thing(one, two); -/// } -/// this.one = one; -/// this.two = two; -/// } -/// ``` -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct MetaProp<'a> { - pub meta: Ident<'a>, - pub property: Ident<'a>, -} - -/// A literal value -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr( - all(feature = "serde", not(feature = "esprima")), - derive(Deserialize, Serialize) -)] -#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum Lit<'a> { - /// `null` - Null, - /// `"string"` - /// `'string'` - String(StringLit<'a>), - /// `0` - /// `0.0` - /// `.0` - /// `0.0e1` - /// `.0E1` - /// `0xf` - /// `0o7` - /// `0b1` - Number(Cow<'a, str>), - /// `true` - /// `false` - Boolean(bool), - /// `/.+/g` - RegEx(RegEx<'a>), - /// ```js - /// `I have ${0} apples` - /// ``` - Template(TemplateLit<'a>), -} - -impl<'a> Lit<'a> { - pub fn number_from(s: &'a str) -> Self { - Lit::Number(Cow::Borrowed(s)) - } - pub fn single_string_from(s: &'a str) -> Self { - Lit::String(StringLit::single_from(s)) - } - pub fn double_string_from(s: &'a str) -> Self { - Lit::String(StringLit::double_from(s)) - } -} - -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub enum StringLit<'a> { - Double(Cow<'a, str>), - Single(Cow<'a, str>), -} - -impl<'a> StringLit<'a> { - pub fn double_from(s: &'a str) -> StringLit<'a> { - StringLit::Double(Cow::Borrowed(s)) - } - pub fn single_from(s: &'a str) -> StringLit<'a> { - StringLit::Single(Cow::Borrowed(s)) - } - pub fn clone_inner(&self) -> Cow<'a, str> { - match self { - StringLit::Single(ref s) => s.clone(), - StringLit::Double(ref s) => s.clone(), - } - } - pub fn inner_matches(&self, o: &str) -> bool { - match self { - StringLit::Single(ref s) => s == o, - StringLit::Double(ref d) => d == o, - } - } -} -/// A regular expression literal -#[derive(PartialEq, Debug, Clone)] -#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -#[cfg_attr(all(feature = "serialization"), serde(rename_all = "camelCase"))] -pub struct RegEx<'a> { - pub pattern: Cow<'a, str>, - pub flags: Cow<'a, str>, -} - -impl<'a> RegEx<'a> { - pub fn from(p: &'a str, f: &'a str) -> Self { - RegEx { - pattern: Cow::Borrowed(p), - flags: Cow::Borrowed(f), - } - } -} +use crate::pat::Pat; +use crate::{AssignOp, BinaryOp, LogicalOp, PropKind, SourceText, UnaryOp, UpdateOp}; +use crate::{Class, Func, FuncArg, FuncBody, Ident}; +/// A slightly more granular program part that a statement +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] +pub enum Expr { + /// `[0,,]` + Array(ArrayExpr), + /// An arrow function + /// ```js + /// () => console.log(); + /// x => { + /// return x; + /// } + /// ``` + ArrowFunc(ArrowFuncExpr), + /// Used for resolving possible sequence expressions + /// that are arrow parameters + ArrowParamPlaceHolder(Vec>, bool), + /// Assignment or update assignment + /// ```js + /// a = 0 + /// b += 1 + /// ``` + Assign(AssignExpr), + /// The `await` keyword followed by another `Expr` + Await(Box>), + /// An operation that has two arguments + Binary(BinaryExpr), + /// A class expression see `Class` + Class(Class), + /// Calling a function or method + Call(CallExpr), + /// A ternery expression + Conditional(ConditionalExpr), + /// see `Function` + Func(Func), + /// An identifier + Ident(Ident), + /// A literal value, see `Literal` + Lit(Lit), + /// A specialized `BinaryExpr` for logical evaluation + /// ```js + /// true && true + /// false || true + /// ``` + Logical(LogicalExpr), + /// Accessing the member of a value + /// ```js + /// b['thing']; + /// c.stuff; + /// ``` + Member(MemberExpr), + /// currently just `new.target` + MetaProp(MetaProp), + /// ```js + /// var a = true ? 'stuff' : 'things'; + /// ``` + /// `{}` + /// Calling a constructor + New(NewExpr), + Obj(ObjExpr), + /// Any sequence of expressions separated with a comma + Sequence(SequenceExpr), + /// `...` followed by an `Expr` + Spread(Box>), + /// `super` + Super, + /// A template literal preceded by a tag function identifier + TaggedTemplate(TaggedTemplateExpr), + /// `this` + This, + /// An operation that has one argument + /// ```js + /// typeof T'; + /// +9; + /// ``` + Unary(UnaryExpr), + /// Increment or decrement + /// ```js + /// 1++ + /// --2 + /// ``` + Update(UpdateExpr), + /// yield a value from inside of a generator function + Yield(YieldExpr), +} + +impl Expr { + pub fn ident_from(inner: T) -> Self { + Self::Ident(Ident { + name: SourceText(inner), + }) + } +} + +/// `[a, b, c]` +pub type ArrayExpr = Vec>>; +/// `{a: 'b', c, ...d}` +pub type ObjExpr = Vec>; +/// A single part of an object literal +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] +pub enum ObjProp { + Prop(Prop), + Spread(Expr), +} + +/// A single part of an object literal or class +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +pub struct Prop { + pub key: PropKey, + pub value: PropValue, + pub kind: PropKind, + pub method: bool, + pub computed: bool, + pub short_hand: bool, + pub is_static: bool, +} + +/// An object literal or class property identifier +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] +pub enum PropKey { + Lit(Lit), + Expr(Expr), + Pat(Pat), +} + +/// The value of an object literal or class property +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] +pub enum PropValue { + Expr(Expr), + Pat(Pat), + None, +} + +/// An operation that takes one argument +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct UnaryExpr { + pub operator: UnaryOp, + pub prefix: bool, + pub argument: Box>, +} + +/// Increment or decrementing a value +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct UpdateExpr { + pub operator: UpdateOp, + pub argument: Box>, + pub prefix: bool, +} + +/// An operation that requires 2 arguments +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct BinaryExpr { + pub operator: BinaryOp, + pub left: Box>, + pub right: Box>, +} + +/// An assignment or update + assignment operation +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct AssignExpr { + pub operator: AssignOp, + pub left: AssignLeft, + pub right: Box>, +} + +/// The value being assigned to +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +#[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] +pub enum AssignLeft { + Pat(Pat), + Expr(Box>), +} + +/// A specialized `BinaryExpr` for logical evaluation +/// ```js +/// true && true +/// false || true +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct LogicalExpr { + pub operator: LogicalOp, + pub left: Box>, + pub right: Box>, +} + +/// Accessing the member of a value +/// ```js +/// b['thing']; +/// c.stuff; +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct MemberExpr { + pub object: Box>, + pub property: Box>, + pub computed: bool, +} + +/// A ternery expression +/// ```js +/// var a = true ? 'stuff' : 'things'; +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct ConditionalExpr { + pub test: Box>, + pub alternate: Box>, + pub consequent: Box>, +} + +/// Calling a function or method +/// ```js +/// Math.random() +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct CallExpr { + pub callee: Box>, + pub arguments: Vec>, +} + +/// Calling a constructor +/// ```js +/// new Uint8Array(32); +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct NewExpr { + pub callee: Box>, + pub arguments: Vec>, +} + +/// A collection of `Exprs` separated by commas +pub type SequenceExpr = Vec>; + +/// An arrow function +/// ```js +/// let x = () => y; +/// let q = x => { +/// return x + 1; +/// } +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct ArrowFuncExpr { + pub id: Option>, + pub params: Vec>, + pub body: ArrowFuncBody, + pub expression: bool, + pub generator: bool, + pub is_async: bool, +} + +/// The body portion of an arrow function can be either an expression or a block of statements +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub enum ArrowFuncBody { + FuncBody(FuncBody), + Expr(Box>), +} + +/// yield a value from inside of a generator function +/// ```js +/// function *gen() { +/// while ((new Date() / 1000) < Number.MAX_VALUE) { +/// yield new Date() / 1000; +/// } +/// } +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct YieldExpr { + pub argument: Option>>, + pub delegate: bool, +} + +/// A Template literal preceded by a function identifier +/// see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) for more details +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct TaggedTemplateExpr { + pub tag: Box>, + pub quasi: TemplateLit, +} + +/// A template string literal +/// ```js +/// `I own ${0} birds`; +/// ``` +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +pub struct TemplateLit { + pub quasis: Vec>, + pub expressions: Vec>, +} + +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +pub enum QuasiQuote { + /// ` + BackTick, + /// ${ + OpenBrace, + /// } + CloseBrace, +} + +/// The text part of a `TemplateLiteral` +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +pub struct TemplateElement { + pub open_quote: QuasiQuote, + /// The non-quoted version + pub content: SourceText, + pub close_quote: QuasiQuote, +} + +impl TemplateElement { + pub fn is_tail(&self) -> bool { + matches!( + self.open_quote, + QuasiQuote::BackTick | QuasiQuote::CloseBrace + ) && matches!(self.close_quote, QuasiQuote::BackTick) + } +} + +/// pretty much just `new.target` +/// ```js +/// function Thing(one, two) { +/// if (!new.target) { +/// return new Thing(one, two); +/// } +/// this.one = one; +/// this.two = two; +/// } +/// ``` +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub struct MetaProp { + pub meta: Ident, + pub property: Ident, +} + +/// A literal value +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(feature = "serde", not(feature = "esprima")), + derive(Deserialize, Serialize) +)] +#[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] +pub enum Lit { + /// `null` + Null, + /// `"string"` + /// `'string'` + String(StringLit), + /// `0` + /// `0.0` + /// `.0` + /// `0.0e1` + /// `.0E1` + /// `0xf` + /// `0o7` + /// `0b1` + Number(SourceText), + /// `true` + /// `false` + Boolean(bool), + /// `/.+/g` + RegEx(RegEx), + /// ```js + /// `I have ${0} apples` + /// ``` + Template(TemplateLit), +} + +impl Lit { + pub fn number_from(s: T) -> Self { + Lit::Number(SourceText(s)) + } + pub fn single_string_from(s: T) -> Self { + Lit::String(StringLit::single_from(s)) + } + pub fn double_string_from(s: T) -> Self { + Lit::String(StringLit::double_from(s)) + } +} + +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +pub enum StringLit { + Double(SourceText), + Single(SourceText), +} + +impl StringLit { + pub fn double_from(s: T) -> StringLit { + StringLit::Double(SourceText(s)) + } + pub fn single_from(s: T) -> StringLit { + StringLit::Single(SourceText(s)) + } +} +impl StringLit +where + T: Clone, +{ + pub fn clone_inner(&self) -> T { + match self { + StringLit::Single(ref s) => s.0.clone(), + StringLit::Double(ref s) => s.0.clone(), + } + } +} + +impl StringLit +where + T: AsRef, +{ + pub fn inner_matches(&self, o: &str) -> bool { + match self { + StringLit::Single(ref s) => o.eq(s.0.as_ref()), + StringLit::Double(ref d) => o.eq(d.0.as_ref()), + } + } +} +/// A regular expression literal +#[derive(PartialEq, Debug, Clone)] +#[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] +#[cfg_attr(all(feature = "serialization"), serde(rename_all = "camelCase"))] +pub struct RegEx { + pub pattern: SourceText, + pub flags: Option>, +} + +impl RegEx { + pub fn from(p: T, f: Option) -> Self { + RegEx { + pattern: SourceText(p), + flags: f.map(SourceText), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 4c77dbb..9774678 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,6 @@ #[macro_use] extern crate serde_derive; -use std::borrow::Cow; - pub mod decl; pub mod expr; pub mod pat; @@ -12,30 +10,108 @@ pub mod serde; pub mod spanned; pub mod stmt; +use std::{borrow::Cow, fmt::Debug, ops::Deref}; + use decl::Decl; use expr::{Expr, Lit, Prop}; use pat::Pat; use stmt::Stmt; +#[derive(Clone, Default)] +pub struct SourceText(pub T); + +impl From for SourceText { + fn from(value: T) -> Self { + Self(value) + } +} + +impl Deref for SourceText<&str> { + type Target = str; + fn deref(&self) -> &Self::Target { + self.0 + } +} + +impl Deref for SourceText { + type Target = str; + fn deref(&self) -> &Self::Target { + self.0.as_str() + } +} + +impl AsRef for SourceText +where + T: AsRef, +{ + fn as_ref(&self) -> &str { + self.0.as_ref() + } +} + +impl std::fmt::Display for SourceText +where + T: std::fmt::Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::cmp::PartialEq for SourceText +where + U: PartialEq, +{ + fn eq(&self, other: &U) -> bool { + other.eq(&self.0) + } +} + +impl<'a> std::cmp::PartialEq> for &'a str { + fn eq(&self, other: &SourceText<&'a str>) -> bool { + (&other.0).eq(self) + } +} + +impl std::fmt::Debug for SourceText +where + T: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", &self.0) + } +} + #[derive(Debug, Clone, PartialEq)] #[cfg_attr( all(feature = "serde", not(feature = "esprima")), derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct Ident<'a> { - pub name: Cow<'a, str>, +pub struct Ident { + pub name: SourceText, +} + +impl<'a> From<&'a str> for Ident<&'a str> { + fn from(value: &'a str) -> Self { + Self { + name: SourceText(value), + } + } } -impl<'a> Ident<'a> { - pub fn new(s: String) -> Self { - Ident { - name: Cow::Owned(s), +impl From for Ident { + fn from(value: String) -> Self { + Self { + name: SourceText(value), } } - pub fn from(s: &'a str) -> Self { - Ident { - name: Cow::Borrowed(s), +} + +impl<'a> From> for Ident> { + fn from(value: Cow<'a, str>) -> Self { + Self { + name: SourceText(value), } } } @@ -51,18 +127,18 @@ impl<'a> Ident<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum Program<'a> { +pub enum Program { /// An ES6 Mod - Mod(Vec>), + Mod(Vec>), /// Not an ES6 Mod - Script(Vec>), + Script(Vec>), } -impl<'a> Program<'a> { - pub fn module(parts: Vec>) -> Self { +impl Program { + pub fn module(parts: Vec>) -> Self { Program::Mod(parts) } - pub fn script(parts: Vec>) -> Self { + pub fn script(parts: Vec>) -> Self { Program::Script(parts) } } @@ -76,20 +152,20 @@ impl<'a> Program<'a> { )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] #[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum ProgramPart<'a> { +pub enum ProgramPart { /// A Directive like `'use strict';` - Dir(Dir<'a>), + Dir(Dir), /// A variable, function or module declaration - Decl(Decl<'a>), + Decl(Decl), /// Any other kind of statement - Stmt(Stmt<'a>), + Stmt(Stmt), } -impl<'a> ProgramPart<'a> { - pub fn decl(inner: Decl<'a>) -> Self { +impl ProgramPart { + pub fn decl(inner: Decl) -> Self { ProgramPart::Decl(inner) } - pub fn stmt(inner: Stmt<'a>) -> Self { + pub fn stmt(inner: Stmt) -> Self { ProgramPart::Stmt(inner) } } @@ -102,9 +178,9 @@ impl<'a> ProgramPart<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct Dir<'a> { - pub expr: Lit<'a>, - pub dir: Cow<'a, str>, +pub struct Dir { + pub expr: Lit, + pub dir: SourceText, } /// A function, this will be part of either a function @@ -119,19 +195,19 @@ pub struct Dir<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct Func<'a> { - pub id: Option>, - pub params: Vec>, - pub body: FuncBody<'a>, +pub struct Func { + pub id: Option>, + pub params: Vec>, + pub body: FuncBody, pub generator: bool, pub is_async: bool, } -impl<'a> Func<'a> { +impl Func { pub fn new( - id: Option>, - params: Vec>, - body: FuncBody<'a>, + id: Option>, + params: Vec>, + body: FuncBody, generator: bool, is_async: bool, ) -> Self { @@ -153,16 +229,16 @@ impl<'a> Func<'a> { )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] #[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum FuncArg<'a> { - Expr(Expr<'a>), - Pat(Pat<'a>), +pub enum FuncArg { + Expr(Expr), + Pat(Pat), } -impl<'a> FuncArg<'a> { - pub fn expr(expr: Expr) -> FuncArg { +impl FuncArg { + pub fn expr(expr: Expr) -> FuncArg { FuncArg::Expr(expr) } - pub fn pat(pat: Pat) -> FuncArg { + pub fn pat(pat: Pat) -> FuncArg { FuncArg::Pat(pat) } } @@ -174,7 +250,7 @@ impl<'a> FuncArg<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct FuncBody<'a>(pub Vec>); +pub struct FuncBody(pub Vec>); /// A way to declare object templates /// ```js /// class Thing { @@ -203,10 +279,10 @@ pub struct FuncBody<'a>(pub Vec>); /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct Class<'a> { - pub id: Option>, - pub super_class: Option>>, - pub body: ClassBody<'a>, +pub struct Class { + pub id: Option>, + pub super_class: Option>>, + pub body: ClassBody, } #[derive(Debug, Clone, PartialEq)] #[cfg_attr( @@ -214,14 +290,10 @@ pub struct Class<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct ClassBody<'a>(pub Vec>); +pub struct ClassBody(pub Vec>); -impl<'a> Class<'a> { - pub fn new( - id: Option>, - super_class: Option>, - body: Vec>, - ) -> Class<'a> { +impl Class { + pub fn new(id: Option>, super_class: Option>, body: Vec>) -> Class { Class { id, super_class: super_class.map(Box::new), @@ -366,7 +438,7 @@ pub enum PropKind { pub mod prelude { pub use crate::decl::{ - Decl, DefaultExportDecl, ExportSpecifier, ImportSpecifier, ModDecl, ModExport, ModImport, + Decl, DefaultExportDecl, ExportSpecifier, ImportSpecifier, ModExport, ModImport, NamedExportDecl, NormalImportSpec, VarDecl, }; pub use crate::expr::{ diff --git a/src/pat.rs b/src/pat.rs index 1b702ad..b1e31c2 100644 --- a/src/pat.rs +++ b/src/pat.rs @@ -9,37 +9,39 @@ use crate::Ident; )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] #[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum Pat<'a> { - Ident(Ident<'a>), - Obj(ObjPat<'a>), - Array(Vec>>), - RestElement(Box>), - Assign(AssignPat<'a>), +pub enum Pat { + Ident(Ident), + Obj(ObjPat), + Array(Vec>>), + RestElement(Box>), + Assign(AssignPat), } -impl<'a> Pat<'a> { - pub fn ident_from(s: &'a str) -> Self { - Pat::Ident(Ident::from(s)) +impl Pat { + pub fn ident_from(inner: T) -> Self { + Self::Ident(Ident { + name: crate::SourceText(inner), + }) } } #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] #[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum ArrayPatPart<'a> { - Pat(Pat<'a>), - Expr(Expr<'a>), +pub enum ArrayPatPart { + Pat(Pat), + Expr(Expr), } /// similar to an `ObjectExpr` -pub type ObjPat<'a> = Vec>; +pub type ObjPat = Vec>; /// A single part of an ObjectPat #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] #[cfg_attr(all(feature = "serde", feature = "esprima"), serde(untagged))] -pub enum ObjPatPart<'a> { - Assign(Prop<'a>), - Rest(Box>), +pub enum ObjPatPart { + Assign(Prop), + Rest(Box>), } /// An assignment as a pattern @@ -49,7 +51,7 @@ pub enum ObjPatPart<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct AssignPat<'a> { - pub left: Box>, - pub right: Box>, +pub struct AssignPat { + pub left: Box>, + pub right: Box>, } diff --git a/src/spanned/convert.rs b/src/spanned/convert.rs new file mode 100644 index 0000000..84c79fc --- /dev/null +++ b/src/spanned/convert.rs @@ -0,0 +1,1013 @@ +//! All conversions from spanned into non-spanned types +//! + +use crate::{ + spanned::{ + decl::{ + Alias, Decl, DefaultExportDeclValue, DefaultImportSpec, ExportSpecifier, + ImportSpecifier, ModExport, ModExportSpecifier, ModImport, NamedExportDecl, + NamespaceImportSpec, NormalImportSpec, VarDecl, + }, + expr::{ + ArrowFuncBody, ArrowFuncExpr, AssignExpr, AssignLeft, BinaryExpr, CallExpr, + ConditionalExpr, Expr, Lit, LogicalExpr, MemberExpr, MetaProp, NewExpr, ObjProp, Prop, + PropInitKey, PropKey, PropMethod, PropValue, RegEx, SequenceExprEntry, StringLit, + TaggedTemplateExpr, TemplateElement, TemplateLit, UnaryExpr, UpdateExpr, YieldExpr, + }, + pat::{ArrayElement, ArrayPat, ArrayPatPart, AssignPat, ObjPat, ObjPatPart, Pat}, + stmt::{ + BlockStmt, CatchClause, DoWhileStmt, FinallyClause, ForInStmt, ForOfStmt, ForStmt, + IfStmt, LabeledStmt, LoopInit, LoopLeft, Stmt, SwitchCase, SwitchStmt, TryStmt, + WhileStmt, WithStmt, + }, + tokens::{AssignOp, BinaryOp, LogicalOp, UnaryOp, UpdateOp}, + Class, ClassBody, Dir, Func, FuncArg, FuncArgEntry, FuncBody, Ident, Program, ProgramPart, + Slice, VarKind, + }, + SourceText, +}; + +mod decl { + use super::*; + + impl From> for crate::decl::Decl { + fn from(other: Decl) -> Self { + match other { + Decl::Var { decls, .. } => crate::decl::Decl::Var( + decls.keyword.into(), + decls.decls.into_iter().map(|d| d.item.into()).collect(), + ), + Decl::Func(inner) => crate::decl::Decl::Func(inner.into()), + Decl::Class(c) => crate::decl::Decl::Class(c.into()), + Decl::Import { import, .. } => { + crate::decl::Decl::Import(Box::new((*import).into())) + } + Decl::Export { export, .. } => { + crate::decl::Decl::Export(Box::new((*export).into())) + } + } + } + } + + impl From> for crate::decl::VarDecl { + fn from(other: VarDecl) -> Self { + Self { + id: other.id.into(), + init: other.init.map(From::from), + } + } + } + + impl From> for crate::decl::ModImport { + fn from(other: ModImport) -> Self { + Self { + source: other.source.into(), + specifiers: other + .specifiers + .into_iter() + .map(|e| e.item.into()) + .collect(), + } + } + } + + impl From> for crate::decl::ImportSpecifier { + fn from(other: ImportSpecifier) -> Self { + match other { + ImportSpecifier::Normal(inner) => { + Self::Normal(inner.specs.into_iter().map(|e| e.item.into()).collect()) + } + ImportSpecifier::Default(inner) => Self::Default(inner.into()), + ImportSpecifier::Namespace(inner) => Self::Namespace(inner.into()), + } + } + } + + impl From> for crate::decl::NormalImportSpec { + fn from(other: NormalImportSpec) -> Self { + let imported: crate::Ident = other.imported.into(); + let alias = other.alias.map(|a| a.ident.into()); + + Self { imported, alias } + } + } + + impl From> for crate::Ident { + fn from(other: DefaultImportSpec) -> Self { + other.id.into() + } + } + + impl From> for crate::Ident { + fn from(other: NamespaceImportSpec) -> Self { + other.ident.into() + } + } + + impl From> for crate::decl::ModExport { + fn from(other: ModExport) -> Self { + other.spec.into() + } + } + + impl From> for crate::decl::ModExport { + fn from(other: ModExportSpecifier) -> Self { + match other { + ModExportSpecifier::Default { keyword: _, value } => Self::Default(value.into()), + ModExportSpecifier::Named(inner) => Self::Named(inner.into()), + ModExportSpecifier::All { + star: _, + alias, + keyword: _, + name, + } => Self::All { + alias: alias.map(|a| a.ident.into()), + name: name.into(), + }, + } + } + } + impl From> for crate::decl::NamedExportDecl { + fn from(other: NamedExportDecl) -> Self { + match other { + NamedExportDecl::Decl(inner) => Self::Decl(inner.into()), + NamedExportDecl::Specifier(inner) => Self::Specifier( + inner + .list + .elements + .into_iter() + .map(|e| e.item.into()) + .collect(), + inner.source.map(|s| s.module.into()), + ), + } + } + } + + impl From> for crate::decl::DefaultExportDecl { + fn from(other: DefaultExportDeclValue) -> Self { + match other { + DefaultExportDeclValue::Decl(inner) => Self::Decl(inner.into()), + DefaultExportDeclValue::Expr(inner) => Self::Expr(inner.into()), + } + } + } + + impl From> for crate::decl::ExportSpecifier { + fn from(other: ExportSpecifier) -> Self { + let local: crate::Ident = other.local.into(); + Self { + local: local, + alias: other.alias.map(|a| a.ident.into()), + } + } + } + + impl From> for crate::Ident { + fn from(other: Alias) -> Self { + other.ident.into() + } + } +} + +mod expr { + use crate::spanned::{ + expr::Boolean, + tokens::{QuasiQuote, Quote}, + }; + + use super::*; + + impl From> for crate::Expr { + fn from(other: Expr) -> Self { + match other { + Expr::Array(inner) => Self::Array( + inner + .elements + .into_iter() + .map(|e| e.item.map(From::from)) + .collect(), + ), + Expr::ArrowFunc(inner) => Self::ArrowFunc(inner.into()), + Expr::ArrowParamPlaceHolder(inner) => Self::ArrowParamPlaceHolder( + inner.args.into_iter().map(|e| From::from(e.item)).collect(), + inner.keyword.is_some(), + ), + Expr::Assign(inner) => Self::Assign(inner.into()), + Expr::Await(inner) => Self::Await(Box::new(inner.expr.into())), + Expr::Binary(inner) => Self::Binary(inner.into()), + Expr::Class(inner) => Self::Class((*inner).into()), + Expr::Call(inner) => Self::Call(inner.into()), + Expr::Conditional(inner) => Self::Conditional(inner.into()), + Expr::Func(inner) => Self::Func(inner.into()), + Expr::Ident(inner) => Self::Ident(inner.into()), + Expr::Lit(inner) => Self::Lit(inner.into()), + Expr::Logical(inner) => Self::Logical(inner.into()), + Expr::Member(inner) => Self::Member(inner.into()), + Expr::MetaProp(inner) => Self::MetaProp(inner.into()), + Expr::New(inner) => Self::New(inner.into()), + Expr::Obj(inner) => { + Self::Obj(inner.props.into_iter().map(|e| e.item.into()).collect()) + } + Expr::Sequence(inner) => { + Self::Sequence(inner.into_iter().map(|e| e.item.into()).collect()) + } + Expr::Spread(inner) => Self::Spread(Box::new(inner.expr.into())), + Expr::Super(_) => Self::Super, + Expr::TaggedTemplate(inner) => Self::TaggedTemplate(inner.into()), + Expr::This(_) => Self::This, + Expr::Unary(inner) => Self::Unary(inner.into()), + Expr::Update(inner) => Self::Update(inner.into()), + Expr::Yield(inner) => Self::Yield(inner.into()), + Expr::Wrapped(inner) => inner.expr.into(), + } + } + } + + impl From> for crate::expr::ObjProp { + fn from(other: ObjProp) -> Self { + match other { + ObjProp::Prop(inner) => Self::Prop(inner.into()), + ObjProp::Spread(inner) => Self::Spread(inner.expr.into()), + } + } + } + + impl From> for crate::expr::Prop { + fn from(other: Prop) -> Self { + match other { + Prop::Init(inner) => Self { + computed: inner.key.brackets.is_some(), + short_hand: inner.colon.is_none(), + key: inner.key.into(), + value: inner + .value + .map(From::from) + .unwrap_or(crate::expr::PropValue::None), + kind: crate::PropKind::Init, + method: false, + is_static: false, + }, + Prop::Method(inner) => Self { + computed: inner.id.brackets.is_some(), + key: inner.id.into(), + value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { + body: inner.body.into(), + generator: inner.star.is_some(), + id: None, + is_async: inner.keyword_async.is_some(), + params: inner.params.into_iter().map(|e| e.item.into()).collect(), + })), + kind: crate::PropKind::Method, + method: true, + short_hand: false, + is_static: inner.keyword_static.is_some(), + }, + Prop::Ctor(inner) => Self { + computed: inner.keyword.brackets.is_some(), + key: inner.keyword.into(), + value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { + body: inner.body.into(), + generator: false, + id: None, + is_async: false, + params: inner.params.into_iter().map(|e| e.item.into()).collect(), + })), + kind: crate::PropKind::Ctor, + is_static: false, + method: true, + short_hand: false, + }, + Prop::Get(inner) => Self { + computed: inner.id.brackets.is_some(), + key: inner.id.into(), + value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { + body: inner.body.into(), + generator: false, + id: None, + is_async: false, + params: Vec::new(), + })), + kind: crate::PropKind::Get, + method: false, + short_hand: false, + is_static: inner.keyword_static.is_some(), + }, + Prop::Set(inner) => Self { + computed: inner.id.brackets.is_some(), + key: inner.id.into(), + value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { + body: inner.body.into(), + generator: false, + id: None, + is_async: false, + params: vec![inner.arg.item.into()], + })), + kind: crate::PropKind::Set, + method: false, + short_hand: false, + is_static: inner.keyword_static.is_some(), + }, + } + } + } + + impl From> for crate::expr::PropKey { + fn from(other: PropInitKey) -> Self { + other.value.into() + } + } + + impl From> for crate::Func { + fn from(other: PropMethod) -> Self { + crate::Func { + id: None, + params: other.params.into_iter().map(|e| e.item.into()).collect(), + body: other.body.into(), + generator: other.star.is_some(), + is_async: other.keyword_async.is_some(), + } + } + } + + impl From> for crate::expr::PropKey { + fn from(other: PropKey) -> Self { + match other { + PropKey::Lit(inner) => Self::Lit(inner.into()), + PropKey::Expr(inner) => Self::Expr(inner.into()), + PropKey::Pat(inner) => Self::Pat(inner.into()), + } + } + } + + impl From> for crate::expr::PropValue { + fn from(other: PropValue) -> Self { + match other { + PropValue::Expr(inner) => Self::Expr(inner.into()), + PropValue::Pat(inner) => Self::Pat(inner.into()), + PropValue::Method(inner) => Self::Expr(crate::expr::Expr::Func(inner.into())), + } + } + } + + impl From> for crate::expr::UnaryExpr { + fn from(other: UnaryExpr) -> Self { + Self { + prefix: other.prefix(), + operator: other.operator.into(), + argument: Box::new(From::from(*other.argument)), + } + } + } + + impl From> for crate::expr::UpdateExpr { + fn from(other: UpdateExpr) -> Self { + let ret = Self { + prefix: other.prefix(), + operator: other.operator.into(), + argument: Box::new(From::from(*other.argument)), + }; + ret + } + } + + impl From> for crate::expr::BinaryExpr { + fn from(other: BinaryExpr) -> Self { + Self { + operator: other.operator.into(), + left: Box::new(From::from(*other.left)), + right: Box::new(From::from(*other.right)), + } + } + } + + impl From> for crate::expr::AssignExpr { + fn from(other: AssignExpr) -> Self { + Self { + operator: other.operator.into(), + left: other.left.into(), + right: Box::new(From::from(*other.right)), + } + } + } + + impl From> for crate::expr::AssignLeft { + fn from(other: AssignLeft) -> Self { + match other { + AssignLeft::Pat(inner) => Self::Pat(inner.into()), + AssignLeft::Expr(inner) => Self::Expr(Box::new(From::from(*inner))), + } + } + } + + impl From> for crate::expr::LogicalExpr { + fn from(other: LogicalExpr) -> Self { + Self { + operator: other.operator.into(), + left: Box::new(From::from(*other.left)), + right: Box::new(From::from(*other.right)), + } + } + } + + impl From> for crate::expr::MemberExpr { + fn from(other: MemberExpr) -> Self { + let computed = other.computed(); + Self { + object: Box::new(From::from(*other.object)), + property: Box::new(From::from(*other.property)), + computed, + } + } + } + + impl From> for crate::expr::ConditionalExpr { + fn from(other: ConditionalExpr) -> Self { + Self { + test: Box::new(From::from(*other.test)), + alternate: Box::new(From::from(*other.alternate)), + consequent: Box::new(From::from(*other.consequent)), + } + } + } + + impl From> for crate::expr::CallExpr { + fn from(other: CallExpr) -> Self { + Self { + callee: Box::new(From::from(*other.callee)), + arguments: other.arguments.into_iter().map(|e| e.item.into()).collect(), + } + } + } + + impl From> for crate::expr::NewExpr { + fn from(other: NewExpr) -> Self { + Self { + callee: Box::new(From::from(*other.callee)), + arguments: other.arguments.into_iter().map(|e| e.item.into()).collect(), + } + } + } + + impl From> for crate::expr::ArrowFuncExpr { + fn from(other: ArrowFuncExpr) -> Self { + let expression = matches!(&other.body, ArrowFuncBody::Expr(_)); + Self { + id: None, + params: other.params.into_iter().map(|e| e.item.into()).collect(), + body: other.body.into(), + expression, + generator: other.star.is_some(), + is_async: other.keyword.is_some(), + } + } + } + + impl From> for crate::expr::ArrowFuncBody { + fn from(other: ArrowFuncBody) -> Self { + match other { + ArrowFuncBody::FuncBody(inner) => Self::FuncBody(inner.into()), + ArrowFuncBody::Expr(inner) => Self::Expr(Box::new(From::from(*inner))), + } + } + } + + impl From> for crate::expr::YieldExpr { + fn from(other: YieldExpr) -> Self { + Self { + argument: other.argument.map(|e| Box::new(From::from(*e))), + delegate: other.star.is_some(), + } + } + } + + impl From> for crate::expr::TaggedTemplateExpr { + fn from(other: TaggedTemplateExpr) -> Self { + Self { + tag: Box::new(From::from(*other.tag)), + quasi: other.quasi.into(), + } + } + } + + impl From> for crate::expr::TemplateLit { + fn from(other: TemplateLit) -> Self { + Self { + quasis: other.quasis.into_iter().map(From::from).collect(), + expressions: other.expressions.into_iter().map(From::from).collect(), + } + } + } + + impl From for crate::expr::QuasiQuote { + fn from(other: QuasiQuote) -> Self { + match other { + QuasiQuote::BackTick(_) => Self::BackTick, + QuasiQuote::CloseBrace(_) => Self::CloseBrace, + QuasiQuote::OpenBrace(_) => Self::OpenBrace, + } + } + } + + impl From> for crate::expr::TemplateElement { + fn from(other: TemplateElement) -> Self { + Self { + open_quote: other.open_quote.into(), + content: other.content.into(), + close_quote: other.close_quote.into(), + } + } + } + + impl From> for crate::expr::MetaProp { + fn from(other: MetaProp) -> Self { + Self { + meta: other.meta.into(), + property: other.property.into(), + } + } + } + + impl From> for crate::expr::Lit { + fn from(other: Lit) -> Self { + match other { + Lit::Null(_inner) => Self::Null, + Lit::String(inner) => Self::String(inner.into()), + Lit::Number(inner) => Self::Number(inner.source), + Lit::Boolean(inner) => Self::Boolean(inner.into()), + Lit::RegEx(inner) => Self::RegEx(inner.into()), + Lit::Template(inner) => Self::Template(inner.into()), + } + } + } + + impl From for bool { + fn from(other: Boolean) -> Self { + match other { + Boolean::True(_) => true, + Boolean::False(_) => false, + } + } + } + + impl From> for crate::expr::StringLit { + fn from(other: StringLit) -> Self { + if matches!(other.open_quote, Quote::Double(_)) { + Self::Double(other.content.source) + } else { + Self::Single(other.content.source) + } + } + } + + impl From> for crate::expr::RegEx { + fn from(other: RegEx) -> Self { + Self { + pattern: other.pattern.source, + flags: other.flags.map(|f| f.source), + } + } + } + + impl From> for crate::expr::Expr { + fn from(other: SequenceExprEntry) -> Self { + other.expr.into() + } + } +} + +impl From> for crate::Ident { + fn from(other: Ident) -> Self { + Self { + name: other.slice.source, + } + } +} + +impl From> for crate::Dir { + fn from(other: Dir) -> Self { + Self { + expr: other.expr.into(), + dir: other.dir, + } + } +} + +impl From> for crate::Func { + fn from(other: Func) -> Self { + Self { + generator: other.generator(), + is_async: other.is_async(), + id: other.id.map(From::from), + params: other + .params + .into_iter() + .map(|e| From::from(e.item)) + .collect(), + body: other.body.into(), + } + } +} + +impl From> for crate::FuncArg { + fn from(other: FuncArgEntry) -> Self { + other.value.into() + } +} + +impl From> for crate::FuncArg { + fn from(other: FuncArg) -> Self { + match other { + FuncArg::Expr(inner) => Self::Expr(inner.into()), + FuncArg::Pat(inner) => Self::Pat(inner.into()), + FuncArg::Rest(inner) => { + Self::Pat(crate::pat::Pat::RestElement(Box::new(inner.pat.into()))) + } + } + } +} + +impl From> for crate::Program { + fn from(other: Program) -> Self { + match other { + Program::Mod(inner) => Self::Mod(inner.into_iter().map(From::from).collect()), + Program::Script(inner) => Self::Script(inner.into_iter().map(From::from).collect()), + } + } +} + +impl From> for crate::ProgramPart { + fn from(other: ProgramPart) -> Self { + match other { + ProgramPart::Dir(inner) => Self::Dir(inner.into()), + ProgramPart::Decl(inner) => Self::Decl(inner.into()), + ProgramPart::Stmt(inner) => Self::Stmt(inner.into()), + } + } +} + +impl From> for crate::FuncBody { + fn from(other: FuncBody) -> Self { + Self(other.stmts.into_iter().map(From::from).collect()) + } +} + +impl From> for crate::Class { + fn from(other: Class) -> Self { + Self { + id: other.id.map(From::from), + super_class: other.super_class.map(|e| Box::new(From::from(e.expr))), + body: other.body.into(), + } + } +} + +impl From> for crate::ClassBody { + fn from(other: ClassBody) -> Self { + Self(other.props.into_iter().map(From::from).collect()) + } +} + +impl From for crate::VarKind { + fn from(other: VarKind) -> Self { + match other { + VarKind::Var(_) => Self::Var, + VarKind::Let(_) => Self::Let, + VarKind::Const(_) => Self::Const, + } + } +} + +impl From for crate::AssignOp { + fn from(other: AssignOp) -> Self { + match other { + AssignOp::Equal(_) => Self::Equal, + AssignOp::PlusEqual(_) => Self::PlusEqual, + AssignOp::MinusEqual(_) => Self::MinusEqual, + AssignOp::TimesEqual(_) => Self::TimesEqual, + AssignOp::DivEqual(_) => Self::DivEqual, + AssignOp::ModEqual(_) => Self::ModEqual, + AssignOp::LeftShiftEqual(_) => Self::LeftShiftEqual, + AssignOp::RightShiftEqual(_) => Self::RightShiftEqual, + AssignOp::UnsignedRightShiftEqual(_) => Self::UnsignedRightShiftEqual, + AssignOp::OrEqual(_) => Self::OrEqual, + AssignOp::XOrEqual(_) => Self::XOrEqual, + AssignOp::AndEqual(_) => Self::AndEqual, + AssignOp::PowerOfEqual(_) => Self::PowerOfEqual, + } + } +} + +impl From for crate::LogicalOp { + fn from(other: LogicalOp) -> Self { + match other { + LogicalOp::Or(_) => Self::Or, + LogicalOp::And(_) => Self::And, + } + } +} + +impl From for crate::BinaryOp { + fn from(other: BinaryOp) -> Self { + match other { + BinaryOp::Equal(_) => Self::Equal, + BinaryOp::NotEqual(_) => Self::NotEqual, + BinaryOp::StrictEqual(_) => Self::StrictEqual, + BinaryOp::StrictNotEqual(_) => Self::StrictNotEqual, + BinaryOp::LessThan(_) => Self::LessThan, + BinaryOp::GreaterThan(_) => Self::GreaterThan, + BinaryOp::LessThanEqual(_) => Self::LessThanEqual, + BinaryOp::GreaterThanEqual(_) => Self::GreaterThanEqual, + BinaryOp::LeftShift(_) => Self::LeftShift, + BinaryOp::RightShift(_) => Self::RightShift, + BinaryOp::UnsignedRightShift(_) => Self::UnsignedRightShift, + BinaryOp::Plus(_) => Self::Plus, + BinaryOp::Minus(_) => Self::Minus, + BinaryOp::Times(_) => Self::Times, + BinaryOp::Over(_) => Self::Over, + BinaryOp::Mod(_) => Self::Mod, + BinaryOp::Or(_) => Self::Or, + BinaryOp::XOr(_) => Self::XOr, + BinaryOp::And(_) => Self::And, + BinaryOp::In(_) => Self::In, + BinaryOp::InstanceOf(_) => Self::InstanceOf, + BinaryOp::PowerOf(_) => Self::PowerOf, + } + } +} + +impl From for crate::UpdateOp { + fn from(other: UpdateOp) -> Self { + match other { + UpdateOp::Increment(_) => Self::Increment, + UpdateOp::Decrement(_) => Self::Decrement, + } + } +} + +impl From for crate::UnaryOp { + fn from(other: UnaryOp) -> Self { + match other { + UnaryOp::Minus(_) => Self::Minus, + UnaryOp::Plus(_) => Self::Plus, + UnaryOp::Not(_) => Self::Not, + UnaryOp::Tilde(_) => Self::Tilde, + UnaryOp::TypeOf(_) => Self::TypeOf, + UnaryOp::Void(_) => Self::Void, + UnaryOp::Delete(_) => Self::Delete, + } + } +} + +mod pat { + use super::*; + + impl From> for crate::pat::Pat { + fn from(other: Pat) -> Self { + match other { + Pat::Ident(inner) => Self::Ident(inner.into()), + Pat::Obj(inner) => Self::Obj(inner.into()), + Pat::Array(inner) => Self::Array(inner.into()), + Pat::Assign(inner) => Self::Assign(inner.into()), + } + } + } + + impl From> for Vec>> { + fn from(other: ArrayPat) -> Self { + other + .elements + .into_iter() + .map(|e| e.item.map(Into::into)) + .collect() + } + } + + impl From> for Option> { + fn from(other: ArrayElement) -> Self { + other.part.map(From::from) + } + } + + impl From> for crate::pat::ArrayPatPart { + fn from(other: ArrayPatPart) -> Self { + match other { + ArrayPatPart::Pat(inner) => Self::Pat(inner.into()), + ArrayPatPart::Expr(inner) => Self::Expr(inner.into()), + ArrayPatPart::Rest(inner) => { + Self::Pat(crate::pat::Pat::RestElement(Box::new(inner.pat.into()))) + } + } + } + } + + impl From> for crate::pat::ObjPat { + fn from(other: ObjPat) -> Self { + other.props.into_iter().map(|e| e.item.into()).collect() + } + } + + impl From> for crate::pat::ObjPatPart { + fn from(other: ObjPatPart) -> Self { + match other { + ObjPatPart::Assign(prop) => Self::Assign(prop.into()), + ObjPatPart::Rest(inner) => Self::Rest(Box::new(From::from(inner.pat))), + } + } + } + + impl From> for crate::pat::AssignPat { + fn from(other: AssignPat) -> Self { + Self { + left: Box::new(From::from(*other.left)), + right: Box::new(From::from(*other.right)), + } + } + } +} +mod stmt { + use super::*; + + impl From> for crate::stmt::Stmt { + fn from(other: Stmt) -> Self { + match other { + Stmt::Expr { expr, .. } => Self::Expr(expr.into()), + Stmt::Block(inner) => Self::Block(inner.into()), + Stmt::Empty(_) => Self::Empty, + Stmt::Debugger { .. } => Self::Debugger, + Stmt::With(inner) => Self::With(inner.into()), + Stmt::Return { value, .. } => Self::Return(value.map(From::from)), + Stmt::Labeled(inner) => Self::Labeled(inner.into()), + Stmt::Break { label, .. } => Self::Break(label.map(From::from)), + Stmt::Continue { label, .. } => Self::Continue(label.map(From::from)), + Stmt::If(inner) => Self::If(inner.into()), + Stmt::Switch(inner) => Self::Switch(inner.into()), + Stmt::Throw { expr, .. } => Self::Throw(expr.into()), + Stmt::Try(inner) => Self::Try(inner.into()), + Stmt::While(inner) => Self::While(inner.into()), + Stmt::DoWhile(inner) => Self::DoWhile(inner.into()), + Stmt::For(inner) => Self::For(inner.into()), + Stmt::ForIn(inner) => Self::ForIn(inner.into()), + Stmt::ForOf(inner) => Self::ForOf(inner.into()), + Stmt::Var { decls, .. } => { + Self::Var(decls.decls.into_iter().map(|e| e.item.into()).collect()) + } + } + } + } + + impl From> for crate::stmt::WithStmt { + fn from(other: WithStmt) -> Self { + Self { + object: other.object.into(), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::LabeledStmt { + fn from(other: LabeledStmt) -> Self { + Self { + label: other.label.into(), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::IfStmt { + fn from(other: IfStmt) -> Self { + Self { + test: other.test.into(), + consequent: Box::new(From::from(*other.consequent)), + alternate: other.alternate.map(|s| Box::new(From::from(s.body))), + } + } + } + + impl From> for crate::stmt::SwitchStmt { + fn from(other: SwitchStmt) -> Self { + Self { + discriminant: other.discriminant.into(), + cases: other.cases.into_iter().map(From::from).collect(), + } + } + } + + impl From> for crate::stmt::SwitchCase { + fn from(other: SwitchCase) -> Self { + Self { + test: other.test.map(From::from), + consequent: other.consequent.into_iter().map(From::from).collect(), + } + } + } + + impl From> for crate::stmt::BlockStmt { + fn from(other: BlockStmt) -> Self { + Self(other.stmts.into_iter().map(From::from).collect()) + } + } + + impl From> for crate::stmt::TryStmt { + fn from(other: TryStmt) -> Self { + Self { + block: other.block.into(), + handler: other.handler.map(From::from), + finalizer: other.finalizer.map(From::from), + } + } + } + + impl From> for crate::stmt::CatchClause { + fn from(other: CatchClause) -> Self { + Self { + param: other.param.map(|a| a.param.into()), + body: other.body.into(), + } + } + } + + impl From> for crate::stmt::BlockStmt { + fn from(other: FinallyClause) -> Self { + other.body.into() + } + } + + impl From> for crate::stmt::WhileStmt { + fn from(other: WhileStmt) -> Self { + Self { + test: other.test.into(), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::DoWhileStmt { + fn from(other: DoWhileStmt) -> Self { + Self { + test: other.test.into(), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::ForStmt { + fn from(other: ForStmt) -> Self { + Self { + init: other.init.map(From::from), + test: other.test.map(From::from), + update: other.update.map(From::from), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::LoopInit { + fn from(other: LoopInit) -> Self { + match other { + LoopInit::Expr(inner) => Self::Expr(inner.into()), + LoopInit::Variable(kind, decls) => Self::Variable( + kind.into(), + decls.into_iter().map(|e| e.item.into()).collect(), + ), + } + } + } + + impl From> for crate::stmt::ForInStmt { + fn from(other: ForInStmt) -> Self { + Self { + left: other.left.into(), + right: other.right.into(), + body: Box::new(From::from(*other.body)), + } + } + } + + impl From> for crate::stmt::ForOfStmt { + fn from(other: ForOfStmt) -> Self { + Self { + left: other.left.into(), + right: other.right.into(), + body: Box::new(From::from(*other.body)), + is_await: other.is_await, + } + } + } + + impl From> for crate::stmt::LoopLeft { + fn from(other: LoopLeft) -> Self { + match other { + LoopLeft::Expr(inner) => Self::Expr(inner.into()), + LoopLeft::Variable(kind, decl) => Self::Variable(kind.into(), decl.into()), + LoopLeft::Pat(inner) => Self::Pat(inner.into()), + } + } + } +} + +impl From> for SourceText { + fn from(other: Slice) -> Self { + other.source + } +} diff --git a/src/spanned/decl.rs b/src/spanned/decl.rs index 0dbaba1..47335f4 100644 --- a/src/spanned/decl.rs +++ b/src/spanned/decl.rs @@ -3,11 +3,14 @@ use crate::spanned::pat::Pat; use crate::spanned::VarKind; use crate::spanned::{Class, Func, Ident}; -use super::{ListEntry, Node, Slice, SourceLocation}; +use super::tokens::{ + As, Asterisk, CloseBrace, Default, Equal, Export, From, Import, OpenBrace, Semicolon, Token, +}; +use super::{ListEntry, Node, SourceLocation}; /// The declaration of a variable, function, class, import or export #[derive(Debug, Clone, PartialEq)] -pub enum Decl<'a> { +pub enum Decl { /// A variable declaration /// ```js /// var x, b; @@ -15,61 +18,46 @@ pub enum Decl<'a> { /// const q = 100 /// ``` Var { - decls: VarDecls<'a>, - semi_colon: Option>, + decls: VarDecls, + semi_colon: Option, }, /// A function declaration /// ```js /// function thing() {} /// ``` - Func(Func<'a>), + Func(Func), /// A class declaration /// ```js /// class Thing {} /// ``` - Class(Class<'a>), + Class(Class), /// An import declaration /// ```js /// import * as moment from 'moment'; /// import Thing, {thing} from 'stuff'; /// ``` Import { - import: Box>, - semi_colon: Option>, + import: Box>, + semi_colon: Option, }, /// An export declaration /// ```js /// export function thing() {} /// ``` Export { - export: Box>, - semi_colon: Option>, + export: Box>, + semi_colon: Option, }, } -impl<'a> From> for crate::decl::Decl<'a> { - fn from(other: Decl<'a>) -> Self { - match other { - Decl::Var { decls, .. } => Self::Var( - decls.keyword.into(), - decls.decls.into_iter().map(|e| e.item.into()).collect(), - ), - Decl::Func(inner) => Self::Func(inner.into()), - Decl::Class(inner) => Self::Class(inner.into()), - Decl::Import { import, .. } => Self::Import(Box::new(From::from(*import))), - Decl::Export { export, .. } => Self::Export(Box::new(From::from(*export))), - } - } -} - -impl<'a> Node for Decl<'a> { +impl Node for Decl { fn loc(&self) -> super::SourceLocation { match self { Decl::Var { decls, semi_colon } => { if let Some(semi) = semi_colon { return SourceLocation { start: decls.loc().start, - end: semi.loc.end, + end: semi.end(), }; } decls.loc() @@ -80,7 +68,7 @@ impl<'a> Node for Decl<'a> { if let Some(semi) = semi_colon { return SourceLocation { start: import.loc().start, - end: semi.loc.end, + end: semi.end(), }; } import.loc() @@ -89,7 +77,7 @@ impl<'a> Node for Decl<'a> { if let Some(semi) = semi_colon { return SourceLocation { start: export.loc().start, - end: semi.loc.end, + end: semi.end(), }; } export.loc() @@ -99,12 +87,12 @@ impl<'a> Node for Decl<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct VarDecls<'a> { - pub keyword: VarKind<'a>, - pub decls: Vec>>, +pub struct VarDecls { + pub keyword: VarKind, + pub decls: Vec>>, } -impl<'a> Node for VarDecls<'a> { +impl Node for VarDecls { fn loc(&self) -> SourceLocation { if let Some(last) = self.decls.last() { SourceLocation { @@ -119,13 +107,13 @@ impl<'a> Node for VarDecls<'a> { /// The identifier and optional value of a variable declaration #[derive(Debug, Clone, PartialEq)] -pub struct VarDecl<'a> { - pub id: Pat<'a>, - pub eq: Option>, - pub init: Option>, +pub struct VarDecl { + pub id: Pat, + pub eq: Option, + pub init: Option>, } -impl<'a> Node for VarDecl<'a> { +impl Node for VarDecl { fn loc(&self) -> SourceLocation { if let Some(init) = &self.init { SourceLocation { @@ -138,25 +126,16 @@ impl<'a> Node for VarDecl<'a> { } } -impl<'a> From> for crate::decl::VarDecl<'a> { - fn from(other: VarDecl<'a>) -> Self { - Self { - id: other.id.into(), - init: other.init.map(From::from), - } - } -} - /// A module declaration, This would only be available /// in an ES Mod, it would be either an import or /// export at the top level #[derive(PartialEq, Debug, Clone)] -pub enum ModDecl<'a> { - Import(ModImport<'a>), - Export(ModExport<'a>), +pub enum ModDecl { + Import(ModImport), + Export(ModExport), } -impl<'a> Node for ModDecl<'a> { +impl Node for ModDecl { fn loc(&self) -> SourceLocation { match self { ModDecl::Import(inner) => inner.loc(), @@ -172,38 +151,25 @@ impl<'a> Node for ModDecl<'a> { /// import {Thing} from './stuff.js'; /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ModImport<'a> { - pub keyword_import: Slice<'a>, - pub specifiers: Vec>>, - pub keyword_from: Option>, - pub source: Lit<'a>, +pub struct ModImport { + pub keyword_import: Import, + pub specifiers: Vec>>, + pub keyword_from: Option, + pub source: Lit, } -impl<'a> Node for ModImport<'a> { +impl Node for ModImport { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword_import.loc.start, + start: self.keyword_import.start(), end: self.source.loc().end, } } } -impl<'a> From> for crate::decl::ModImport<'a> { - fn from(other: ModImport<'a>) -> Self { - Self { - source: other.source.into(), - specifiers: other - .specifiers - .into_iter() - .map(|e| e.item.into()) - .collect(), - } - } -} - /// The name of the thing being imported #[derive(Debug, Clone, PartialEq)] -pub enum ImportSpecifier<'a> { +pub enum ImportSpecifier { /// A specifier in curly braces, this might /// have a local alias /// @@ -213,24 +179,24 @@ pub enum ImportSpecifier<'a> { /// import {People as Persons, x} from './places.js'; /// // ^^^^^^^^^^^^^^^^^^^^^^ /// ``` - Normal(NormalImportSpecs<'a>), + Normal(NormalImportSpecs), /// A specifier that has been exported with the /// default keyword, this should not be wrapped in /// curly braces. /// ```js /// import DefaultThing from './stuff/js'; /// ``` - Default(DefaultImportSpec<'a>), + Default(DefaultImportSpec), /// Import all exported members from a module /// in a namespace. /// /// ```js /// import * as Moment from 'moment.js'; /// ``` - Namespace(NamespaceImportSpec<'a>), + Namespace(NamespaceImportSpec), } -impl<'a> Node for ImportSpecifier<'a> { +impl Node for ImportSpecifier { fn loc(&self) -> SourceLocation { match self { ImportSpecifier::Normal(inner) => inner.loc(), @@ -240,53 +206,29 @@ impl<'a> Node for ImportSpecifier<'a> { } } -impl<'a> From> for crate::decl::ImportSpecifier<'a> { - fn from(other: ImportSpecifier<'a>) -> Self { - match other { - ImportSpecifier::Normal(inner) => { - Self::Normal(inner.specs.into_iter().map(|e| e.item.into()).collect()) - } - ImportSpecifier::Default(inner) => Self::Default(inner.into()), - ImportSpecifier::Namespace(inner) => Self::Namespace(inner.into()), - } - } -} - #[derive(PartialEq, Debug, Clone)] -pub struct NormalImportSpecs<'a> { - pub open_brace: Slice<'a>, - pub specs: Vec>>, - pub close_brace: Slice<'a>, +pub struct NormalImportSpecs { + pub open_brace: OpenBrace, + pub specs: Vec>>, + pub close_brace: CloseBrace, } -impl<'a> Node for NormalImportSpecs<'a> { +impl Node for NormalImportSpecs { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } -impl<'a> From> for crate::decl::NormalImportSpec<'a> { - fn from(other: NormalImportSpec<'a>) -> Self { - let imported: crate::Ident = other.imported.into(); - let local: crate::Ident = if let Some(alias) = other.alias { - alias.into() - } else { - imported.clone() - }; - Self { local, imported } - } -} - #[derive(PartialEq, Debug, Clone)] -pub struct NormalImportSpec<'a> { - pub imported: Ident<'a>, - pub alias: Option>, +pub struct NormalImportSpec { + pub imported: Ident, + pub alias: Option>, } -impl<'a> Node for NormalImportSpec<'a> { +impl Node for NormalImportSpec { fn loc(&self) -> SourceLocation { if let Some(alias) = &self.alias { SourceLocation { @@ -300,76 +242,58 @@ impl<'a> Node for NormalImportSpec<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct DefaultImportSpec<'a> { - pub id: Ident<'a>, -} - -impl<'a> From> for crate::Ident<'a> { - fn from(other: DefaultImportSpec<'a>) -> Self { - other.id.into() - } +pub struct DefaultImportSpec { + pub id: Ident, } -impl<'a> Node for DefaultImportSpec<'a> { +impl Node for DefaultImportSpec { fn loc(&self) -> SourceLocation { self.id.loc() } } #[derive(Debug, Clone, PartialEq)] -pub struct NamespaceImportSpec<'a> { - pub star: Slice<'a>, - pub keyword: Slice<'a>, - pub ident: Ident<'a>, +pub struct NamespaceImportSpec { + pub star: Asterisk, + pub keyword: From, + pub ident: Ident, } -impl<'a> Node for NamespaceImportSpec<'a> { +impl Node for NamespaceImportSpec { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.star.loc.start, + start: self.star.start(), end: self.ident.loc().end, } } } -impl<'a> From> for crate::Ident<'a> { - fn from(other: NamespaceImportSpec<'a>) -> Self { - other.ident.into() - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct ModExport<'a> { - pub keyword: Slice<'a>, - pub spec: ModExportSpecifier<'a>, +pub struct ModExport { + pub keyword: Export, + pub spec: ModExportSpecifier, } -impl<'a> Node for ModExport<'a> { +impl Node for ModExport { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.spec.loc().end, } } } -impl<'a> From> for crate::decl::ModExport<'a> { - fn from(other: ModExport<'a>) -> Self { - other.spec.into() - } -} - /// Something exported from this module #[derive(Debug, Clone, PartialEq)] -pub enum ModExportSpecifier<'a> { +pub enum ModExportSpecifier { /// ```js /// export default function() {}; /// //or /// export default 1; /// ``` Default { - keyword: Slice<'a>, - value: DefaultExportDeclValue<'a>, + keyword: Default, + value: DefaultExportDeclValue, }, ///```js /// export {foo} from 'mod'; @@ -381,63 +305,45 @@ pub enum ModExportSpecifier<'a> { /// export function bar() { /// } /// ``` - Named(NamedExportDecl<'a>), + Named(NamedExportDecl), /// ```js /// export * from 'mod'; /// ``` All { - star: Slice<'a>, - alias: Option>, - keyword: Slice<'a>, - name: Lit<'a>, + star: Asterisk, + alias: Option>, + keyword: From, + name: Lit, }, } -impl<'a> Node for ModExportSpecifier<'a> { +impl Node for ModExportSpecifier { fn loc(&self) -> SourceLocation { match self { ModExportSpecifier::Default { keyword, value } => SourceLocation { - start: keyword.loc.start, + start: keyword.start(), end: value.loc().end, }, ModExportSpecifier::Named(inner) => inner.loc(), ModExportSpecifier::All { star, name, .. } => SourceLocation { - start: star.loc.start, + start: star.start(), end: name.loc().end, }, } } } -impl<'a> From> for crate::decl::ModExport<'a> { - fn from(other: ModExportSpecifier<'a>) -> Self { - match other { - ModExportSpecifier::Default { keyword: _, value } => Self::Default(value.into()), - ModExportSpecifier::Named(inner) => Self::Named(inner.into()), - ModExportSpecifier::All { - star: _, - alias, - keyword: _, - name, - } => Self::All { - alias: alias.map(|a| a.ident.into()), - name: name.into() - }, - } - } -} - /// An export that has a name /// ```js /// export function thing() {} /// export {stuff} from 'place'; #[derive(PartialEq, Debug, Clone)] -pub enum NamedExportDecl<'a> { - Decl(Decl<'a>), - Specifier(NamedExportSpec<'a>), +pub enum NamedExportDecl { + Decl(Decl), + Specifier(NamedExportSpec), } -impl<'a> Node for NamedExportDecl<'a> { +impl Node for NamedExportDecl { fn loc(&self) -> SourceLocation { match self { NamedExportDecl::Decl(inner) => inner.loc(), @@ -446,33 +352,16 @@ impl<'a> Node for NamedExportDecl<'a> { } } -impl<'a> From> for crate::decl::NamedExportDecl<'a> { - fn from(other: NamedExportDecl<'a>) -> Self { - match other { - NamedExportDecl::Decl(inner) => Self::Decl(inner.into()), - NamedExportDecl::Specifier(inner) => Self::Specifier( - inner - .list - .elements - .into_iter() - .map(|e| e.item.into()) - .collect(), - inner.source.map(|s| s.module.into()), - ), - } - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct DefaultExportDecl<'a> { - pub keyword: Slice<'a>, - pub value: DefaultExportDeclValue<'a>, +pub struct DefaultExportDecl { + pub keyword: Default, + pub value: DefaultExportDeclValue, } -impl<'a> Node for DefaultExportDecl<'a> { +impl Node for DefaultExportDecl { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.value.loc().end, } } @@ -483,13 +372,13 @@ impl<'a> Node for DefaultExportDecl<'a> { /// export default class Thing {} /// ``` #[derive(Debug, Clone, PartialEq)] -pub enum ExportDeclValue<'a> { - Decl(Decl<'a>), - Expr(Expr<'a>), - List(ExportList<'a>), +pub enum ExportDeclValue { + Decl(Decl), + Expr(Expr), + List(ExportList), } -impl<'a> Node for ExportDeclValue<'a> { +impl Node for ExportDeclValue { fn loc(&self) -> SourceLocation { match self { ExportDeclValue::Decl(inner) => inner.loc(), @@ -500,12 +389,12 @@ impl<'a> Node for ExportDeclValue<'a> { } #[derive(Debug, Clone, PartialEq)] -pub enum DefaultExportDeclValue<'a> { - Decl(Decl<'a>), - Expr(Expr<'a>), +pub enum DefaultExportDeclValue { + Decl(Decl), + Expr(Expr), } -impl<'a> Node for DefaultExportDeclValue<'a> { +impl Node for DefaultExportDeclValue { fn loc(&self) -> SourceLocation { match self { Self::Decl(inner) => inner.loc(), @@ -514,22 +403,13 @@ impl<'a> Node for DefaultExportDeclValue<'a> { } } -impl<'a> From> for crate::decl::DefaultExportDecl<'a> { - fn from(other: DefaultExportDeclValue<'a>) -> Self { - match other { - DefaultExportDeclValue::Decl(inner) => Self::Decl(inner.into()), - DefaultExportDeclValue::Expr(inner) => Self::Expr(inner.into()), - } - } -} - #[derive(PartialEq, Debug, Clone)] -pub struct NamedExportSpec<'a> { - pub list: ExportList<'a>, - pub source: Option>, +pub struct NamedExportSpec { + pub list: ExportList, + pub source: Option>, } -impl<'a> Node for NamedExportSpec<'a> { +impl Node for NamedExportSpec { fn loc(&self) -> SourceLocation { if let Some(source) = &self.source { SourceLocation { @@ -543,32 +423,32 @@ impl<'a> Node for NamedExportSpec<'a> { } #[derive(PartialEq, Debug, Clone)] -pub struct NamedExportSource<'a> { - pub keyword_from: Slice<'a>, - pub module: Lit<'a>, +pub struct NamedExportSource { + pub keyword_from: From, + pub module: Lit, } -impl<'a> Node for NamedExportSource<'a> { +impl Node for NamedExportSource { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword_from.loc.start, + start: self.keyword_from.start(), end: self.module.loc().end, } } } #[derive(Debug, Clone, PartialEq)] -pub struct ExportList<'a> { - pub open_brace: Slice<'a>, - pub elements: Vec>>, - pub close_brace: Slice<'a>, +pub struct ExportList { + pub open_brace: OpenBrace, + pub elements: Vec>>, + pub close_brace: CloseBrace, } -impl<'a> Node for ExportList<'a> { +impl Node for ExportList { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } @@ -582,12 +462,12 @@ impl<'a> Node for ExportList<'a> { /// export {Stuff as NewThing} from 'place' /// ``` #[derive(Debug, Clone, PartialEq)] -pub struct ExportSpecifier<'a> { - pub local: Ident<'a>, - pub alias: Option>, +pub struct ExportSpecifier { + pub local: Ident, + pub alias: Option>, } -impl<'a> Node for ExportSpecifier<'a> { +impl Node for ExportSpecifier { fn loc(&self) -> SourceLocation { if let Some(alias) = &self.alias { SourceLocation { @@ -600,33 +480,17 @@ impl<'a> Node for ExportSpecifier<'a> { } } -impl<'a> From> for crate::decl::ExportSpecifier<'a> { - fn from(other: ExportSpecifier<'a>) -> Self { - let local: crate::Ident = other.local.into(); - Self { - local: local.clone(), - exported: other.alias.map(|a| a.ident.into()).unwrap_or(local), - } - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct Alias<'a> { - pub keyword: Slice<'a>, - pub ident: Ident<'a>, +pub struct Alias { + pub keyword: As, + pub ident: Ident, } -impl<'a> Node for Alias<'a> { +impl Node for Alias { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.ident.loc().end, } } } - -impl<'a> From> for crate::Ident<'a> { - fn from(other: Alias<'a>) -> Self { - other.ident.into() - } -} diff --git a/src/spanned/expr.rs b/src/spanned/expr.rs index 4f719f6..a7ae64d 100644 --- a/src/spanned/expr.rs +++ b/src/spanned/expr.rs @@ -1,16 +1,19 @@ -use std::borrow::Cow; - use crate::spanned::pat::Pat; -use crate::spanned::{AssignOp, BinaryOp, LogicalOp, UnaryOp, UpdateOp}; use crate::spanned::{Class, Func, FuncArg, FuncBody, Ident}; -use super::{FuncArgEntry, ListEntry, Node, Position, Slice, SourceLocation}; +use super::tokens::{ + AssignOp, Asterisk, Async, Await, BinaryOp, CloseBrace, CloseBracket, CloseParen, Colon, Comma, + Ellipsis, False, FatArrow, ForwardSlash, Get, LogicalOp, New, Null, OpenBrace, OpenBracket, + OpenParen, Period, QuasiQuote, QuestionMark, Quote, Set, Static, Super, This, Token, True, + UnaryOp, UpdateOp, Yield, +}; +use super::{FuncArgEntry, ListEntry, Node, Slice, SourceLocation}; /// A slightly more granular program part that a statement #[derive(Debug, Clone, PartialEq)] -pub enum Expr<'a> { +pub enum Expr { /// `[0,,]` - Array(ArrayExpr<'a>), + Array(ArrayExpr), /// An arrow function /// ```js /// () => console.log(); @@ -18,125 +21,81 @@ pub enum Expr<'a> { /// return x; /// } /// ``` - ArrowFunc(ArrowFuncExpr<'a>), + ArrowFunc(ArrowFuncExpr), /// Used for resolving possible sequence expressions /// that are arrow parameters - ArrowParamPlaceHolder(ArrowParamPlaceHolder<'a>), + ArrowParamPlaceHolder(ArrowParamPlaceHolder), /// Assignment or update assignment /// ```js /// a = 0 /// b += 1 /// ``` - Assign(AssignExpr<'a>), + Assign(AssignExpr), /// The `await` keyword followed by another `Expr` - Await(Box>), + Await(Box>), /// An operation that has two arguments - Binary(BinaryExpr<'a>), + Binary(BinaryExpr), /// A class expression see `Class` - Class(Box>), + Class(Box>), /// Calling a function or method - Call(CallExpr<'a>), + Call(CallExpr), /// A ternery expression - Conditional(ConditionalExpr<'a>), + Conditional(ConditionalExpr), /// see `Function` - Func(Func<'a>), + Func(Func), /// An identifier - Ident(Ident<'a>), + Ident(Ident), /// A literal value, see `Literal` - Lit(Lit<'a>), + Lit(Lit), /// A specialized `BinaryExpr` for logical evaluation /// ```js /// true && true /// false || true /// ``` - Logical(LogicalExpr<'a>), + Logical(LogicalExpr), /// Accessing the member of a value /// ```js /// b['thing']; /// c.stuff; /// ``` - Member(MemberExpr<'a>), + Member(MemberExpr), /// currently just `new.target` - MetaProp(MetaProp<'a>), + MetaProp(MetaProp), /// ```js /// var a = true ? 'stuff' : 'things'; /// ``` /// `{}` /// Calling a constructor - New(NewExpr<'a>), - Obj(ObjExpr<'a>), + New(NewExpr), + Obj(ObjExpr), /// Any sequence of expressions separated with a comma - Sequence(SequenceExpr<'a>), + Sequence(SequenceExpr), /// `...` followed by an `Expr` - Spread(Box>), + Spread(Box>), /// `super` - Super(Slice<'a>), + Super(Super), /// A template literal preceded by a tag function identifier - TaggedTemplate(TaggedTemplateExpr<'a>), + TaggedTemplate(TaggedTemplateExpr), /// `this` - This(Slice<'a>), + This(This), /// An operation that has one argument /// ```js - /// typeof 'a'; + /// typeof T'; /// +9; /// ``` - Unary(UnaryExpr<'a>), + Unary(UnaryExpr), /// Increment or decrement /// ```js /// 1++ /// --2 /// ``` - Update(UpdateExpr<'a>), - Wrapped(Box>), + Update(UpdateExpr), + Wrapped(Box>), /// yield a value from inside of a generator function - Yield(YieldExpr<'a>), -} - -impl<'a> From> for crate::Expr<'a> { - fn from(other: Expr<'a>) -> Self { - match other { - Expr::Array(inner) => Self::Array( - inner - .elements - .into_iter() - .map(|e| e.item.map(From::from)) - .collect(), - ), - Expr::ArrowFunc(inner) => Self::ArrowFunc(inner.into()), - Expr::ArrowParamPlaceHolder(inner) => Self::ArrowParamPlaceHolder( - inner.args.into_iter().map(|e| From::from(e.item)).collect(), - inner.keyword.is_some(), - ), - Expr::Assign(inner) => Self::Assign(inner.into()), - Expr::Await(inner) => Self::Await(Box::new(inner.expr.into())), - Expr::Binary(inner) => Self::Binary(inner.into()), - Expr::Class(inner) => Self::Class((*inner).into()), - Expr::Call(inner) => Self::Call(inner.into()), - Expr::Conditional(inner) => Self::Conditional(inner.into()), - Expr::Func(inner) => Self::Func(inner.into()), - Expr::Ident(inner) => Self::Ident(inner.into()), - Expr::Lit(inner) => Self::Lit(inner.into()), - Expr::Logical(inner) => Self::Logical(inner.into()), - Expr::Member(inner) => Self::Member(inner.into()), - Expr::MetaProp(inner) => Self::MetaProp(inner.into()), - Expr::New(inner) => Self::New(inner.into()), - Expr::Obj(inner) => Self::Obj(inner.props.into_iter().map(|e| e.item.into()).collect()), - Expr::Sequence(inner) => { - Self::Sequence(inner.into_iter().map(|e| e.item.into()).collect()) - } - Expr::Spread(inner) => Self::Spread(Box::new(inner.expr.into())), - Expr::Super(_) => Self::Super, - Expr::TaggedTemplate(inner) => Self::TaggedTemplate(inner.into()), - Expr::This(_) => Self::This, - Expr::Unary(inner) => Self::Unary(inner.into()), - Expr::Update(inner) => Self::Update(inner.into()), - Expr::Yield(inner) => Self::Yield(inner.into()), - Expr::Wrapped(inner) => inner.expr.into(), - } - } + Yield(YieldExpr), } -impl<'a> Node for Expr<'a> { +impl Node for Expr { fn loc(&self) -> SourceLocation { match self { Expr::Array(inner) => inner.loc(), @@ -158,9 +117,9 @@ impl<'a> Node for Expr<'a> { Expr::Obj(inner) => inner.loc(), Expr::Sequence(inner) => inner.loc(), Expr::Spread(inner) => inner.loc(), - Expr::Super(inner) => inner.loc, + Expr::Super(inner) => inner.loc(), Expr::TaggedTemplate(inner) => inner.loc(), - Expr::This(inner) => inner.loc, + Expr::This(inner) => inner.loc(), Expr::Unary(inner) => inner.loc(), Expr::Update(inner) => inner.loc(), Expr::Yield(inner) => inner.loc(), @@ -169,59 +128,50 @@ impl<'a> Node for Expr<'a> { } } -type ArrayExprEntry<'a> = ListEntry<'a, Option>>; +type ArrayExprEntry = ListEntry>>; /// `[a, b, c]` #[derive(Debug, Clone, PartialEq)] -pub struct ArrayExpr<'a> { - pub open_bracket: Slice<'a>, - pub elements: Vec>, - pub close_bracket: Slice<'a>, +pub struct ArrayExpr { + pub open_bracket: OpenBracket, + pub elements: Vec>, + pub close_bracket: CloseBracket, } -impl<'a> Node for ArrayExpr<'a> { +impl Node for ArrayExpr { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_bracket.loc.start, - end: self.close_bracket.loc.end, + start: self.open_bracket.start(), + end: self.close_bracket.end(), } } } /// `{a: 'b', c, ...d}` #[derive(Debug, Clone, PartialEq)] -pub struct ObjExpr<'a> { - pub open_brace: Slice<'a>, - pub props: Vec>>, - pub close_brace: Slice<'a>, +pub struct ObjExpr { + pub open_brace: OpenBrace, + pub props: Vec>>, + pub close_brace: CloseBrace, } -impl<'a> Node for ObjExpr<'a> { +impl Node for ObjExpr { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } /// A single part of an object literal #[derive(PartialEq, Debug, Clone)] -pub enum ObjProp<'a> { - Prop(Prop<'a>), - Spread(SpreadExpr<'a>), -} - -impl<'a> From> for crate::expr::ObjProp<'a> { - fn from(other: ObjProp<'a>) -> Self { - match other { - ObjProp::Prop(inner) => Self::Prop(inner.into()), - ObjProp::Spread(inner) => Self::Spread(inner.expr.into()), - } - } +pub enum ObjProp { + Prop(Prop), + Spread(SpreadExpr), } -impl<'a> Node for ObjProp<'a> { +impl Node for ObjProp { fn loc(&self) -> SourceLocation { match self { ObjProp::Prop(inner) => inner.loc(), @@ -231,109 +181,30 @@ impl<'a> Node for ObjProp<'a> { } #[derive(PartialEq, Debug, Clone)] -pub struct SpreadExpr<'a> { - pub dots: Slice<'a>, - pub expr: Expr<'a>, +pub struct SpreadExpr { + pub dots: Ellipsis, + pub expr: Expr, } -impl<'a> Node for SpreadExpr<'a> { +impl Node for SpreadExpr { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.dots.loc.start, + start: self.dots.start(), end: self.expr.loc().end, } } } #[derive(Debug, Clone, PartialEq)] -pub enum Prop<'a> { - Init(PropInit<'a>), - Method(PropMethod<'a>), - Ctor(PropCtor<'a>), - Get(PropGet<'a>), - Set(PropSet<'a>), -} - -impl<'a> From> for crate::expr::Prop<'a> { - fn from(other: Prop<'a>) -> Self { - match other { - Prop::Init(inner) => Self { - computed: inner.key.brackets.is_some(), - short_hand: inner.colon.is_none(), - key: inner.key.into(), - value: inner - .value - .map(From::from) - .unwrap_or(crate::expr::PropValue::None), - kind: crate::PropKind::Init, - method: false, - is_static: false, - }, - Prop::Method(inner) => Self { - computed: inner.id.brackets.is_some(), - key: inner.id.into(), - value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { - body: inner.body.into(), - generator: inner.star.is_some(), - id: None, - is_async: inner.keyword_async.is_some(), - params: inner.params.into_iter().map(|e| e.item.into()).collect(), - })), - kind: crate::PropKind::Method, - method: true, - short_hand: false, - is_static: inner.keyword_static.is_some(), - }, - Prop::Ctor(inner) => Self { - computed: inner.keyword.brackets.is_some(), - key: inner.keyword.into(), - value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { - body: inner.body.into(), - generator: false, - id: None, - is_async: false, - params: inner.params.into_iter().map(|e| e.item.into()).collect(), - })), - kind: crate::PropKind::Ctor, - is_static: false, - method: true, - short_hand: false, - }, - Prop::Get(inner) => Self { - computed: inner.id.brackets.is_some(), - key: inner.id.into(), - value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { - body: inner.body.into(), - generator: false, - id: None, - is_async: false, - params: Vec::new(), - })), - kind: crate::PropKind::Get, - method: false, - short_hand: false, - is_static: inner.keyword_static.is_some(), - }, - Prop::Set(inner) => Self { - computed: inner.id.brackets.is_some(), - key: inner.id.into(), - value: crate::prelude::PropValue::Expr(crate::Expr::Func(crate::Func { - body: inner.body.into(), - generator: false, - id: None, - is_async: false, - params: vec![inner.arg.item.into()], - })), - kind: crate::PropKind::Set, - method: false, - short_hand: false, - is_static: inner.keyword_static.is_some(), - }, - } - } +pub enum Prop { + Init(PropInit), + Method(PropMethod), + Ctor(PropCtor), + Get(PropGet), + Set(PropSet), } -impl<'a> Node for Prop<'a> { +impl Node for Prop { fn loc(&self) -> SourceLocation { match self { Prop::Init(inner) => inner.loc(), @@ -345,7 +216,7 @@ impl<'a> Node for Prop<'a> { } } -impl<'a> Prop<'a> { +impl Prop { pub fn computed(&self) -> bool { if let Self::Init(init) = self { init.computed() @@ -370,13 +241,13 @@ impl<'a> Prop<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct PropInit<'a> { - pub key: PropInitKey<'a>, - pub colon: Option>, - pub value: Option>, +pub struct PropInit { + pub key: PropInitKey, + pub colon: Option, + pub value: Option>, } -impl<'a> Node for PropInit<'a> { +impl Node for PropInit { fn loc(&self) -> SourceLocation { if let Some(value) = &self.value { SourceLocation { @@ -389,7 +260,7 @@ impl<'a> Node for PropInit<'a> { } } -impl<'a> PropInit<'a> { +impl PropInit { pub fn computed(&self) -> bool { self.key.brackets.is_some() } @@ -399,23 +270,17 @@ impl<'a> PropInit<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct PropInitKey<'a> { - pub value: PropKey<'a>, - pub brackets: Option<(Slice<'a>, Slice<'a>)>, +pub struct PropInitKey { + pub value: PropKey, + pub brackets: Option<(OpenBracket, CloseBracket)>, } -impl<'a> From> for crate::expr::PropKey<'a> { - fn from(other: PropInitKey<'a>) -> Self { - other.value.into() - } -} - -impl<'a> Node for PropInitKey<'a> { +impl Node for PropInitKey { fn loc(&self) -> SourceLocation { if let Some((open, close)) = &self.brackets { SourceLocation { - start: open.loc.start, - end: close.loc.end, + start: open.start(), + end: close.end(), } } else { self.value.loc() @@ -424,23 +289,23 @@ impl<'a> Node for PropInitKey<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct PropMethod<'a> { - pub keyword_static: Option>, - pub keyword_async: Option>, - pub id: PropInitKey<'a>, - pub star: Option>, - pub open_paren: Slice<'a>, - pub params: Vec>>, - pub close_paren: Slice<'a>, - pub body: FuncBody<'a>, -} - -impl<'a> Node for PropMethod<'a> { +pub struct PropMethod { + pub keyword_static: Option, + pub keyword_async: Option, + pub id: PropInitKey, + pub star: Option, + pub open_paren: OpenParen, + pub params: Vec>>, + pub close_paren: CloseParen, + pub body: FuncBody, +} + +impl Node for PropMethod { fn loc(&self) -> SourceLocation { let start = if let Some(keyword) = &self.keyword_async { - keyword.loc.start + keyword.start() } else if let Some(star) = &self.star { - star.loc.start + star.start() } else { self.id.loc().start }; @@ -451,28 +316,16 @@ impl<'a> Node for PropMethod<'a> { } } -impl<'a> From> for crate::Func<'a> { - fn from(other: PropMethod<'a>) -> Self { - crate::Func { - id: None, - params: other.params.into_iter().map(|e| e.item.into()).collect(), - body: other.body.into(), - generator: other.star.is_some(), - is_async: other.keyword_async.is_some(), - } - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct PropCtor<'a> { - pub keyword: PropInitKey<'a>, - pub open_paren: Slice<'a>, - pub params: Vec>>, - pub close_paren: Slice<'a>, - pub body: FuncBody<'a>, +pub struct PropCtor { + pub keyword: PropInitKey, + pub open_paren: OpenParen, + pub params: Vec>>, + pub close_paren: CloseParen, + pub body: FuncBody, } -impl<'a> Node for PropCtor<'a> { +impl Node for PropCtor { fn loc(&self) -> SourceLocation { SourceLocation { start: self.keyword.loc().start, @@ -482,51 +335,51 @@ impl<'a> Node for PropCtor<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct PropGet<'a> { - pub keyword_static: Option>, - pub keyword_get: Slice<'a>, - pub id: PropInitKey<'a>, - pub open_paren: Slice<'a>, - pub close_paren: Slice<'a>, - pub body: FuncBody<'a>, +pub struct PropGet { + pub keyword_static: Option, + pub keyword_get: Get, + pub id: PropInitKey, + pub open_paren: OpenParen, + pub close_paren: CloseParen, + pub body: FuncBody, } -impl<'a> Node for PropGet<'a> { +impl Node for PropGet { fn loc(&self) -> SourceLocation { if let Some(keyword_static) = &self.keyword_static { return SourceLocation { - start: keyword_static.loc.start, + start: keyword_static.start(), end: self.body.loc().end, }; } SourceLocation { - start: self.keyword_get.loc.start, + start: self.keyword_get.start(), end: self.body.loc().end, } } } #[derive(Debug, Clone, PartialEq)] -pub struct PropSet<'a> { - pub keyword_static: Option>, - pub keyword_set: Slice<'a>, - pub id: PropInitKey<'a>, - pub open_paren: Slice<'a>, - pub arg: ListEntry<'a, FuncArg<'a>>, - pub close_paren: Slice<'a>, - pub body: FuncBody<'a>, +pub struct PropSet { + pub keyword_static: Option, + pub keyword_set: Set, + pub id: PropInitKey, + pub open_paren: OpenParen, + pub arg: ListEntry>, + pub close_paren: CloseParen, + pub body: FuncBody, } -impl<'a> Node for PropSet<'a> { +impl Node for PropSet { fn loc(&self) -> SourceLocation { if let Some(keyword_static) = &self.keyword_static { return SourceLocation { - start: keyword_static.loc.start, + start: keyword_static.start(), end: self.body.loc().end, }; } SourceLocation { - start: self.keyword_set.loc.start, + start: self.keyword_set.start(), end: self.body.loc().end, } } @@ -534,23 +387,13 @@ impl<'a> Node for PropSet<'a> { /// An object literal or class property identifier #[derive(PartialEq, Debug, Clone)] -pub enum PropKey<'a> { - Lit(Lit<'a>), - Expr(Expr<'a>), - Pat(Pat<'a>), -} - -impl<'a> From> for crate::expr::PropKey<'a> { - fn from(other: PropKey<'a>) -> Self { - match other { - PropKey::Lit(inner) => Self::Lit(inner.into()), - PropKey::Expr(inner) => Self::Expr(inner.into()), - PropKey::Pat(inner) => Self::Pat(inner.into()), - } - } +pub enum PropKey { + Lit(Lit), + Expr(Expr), + Pat(Pat), } -impl<'a> Node for PropKey<'a> { +impl Node for PropKey { fn loc(&self) -> SourceLocation { match self { PropKey::Lit(inner) => inner.loc(), @@ -562,23 +405,13 @@ impl<'a> Node for PropKey<'a> { /// The value of an object literal or class property #[derive(PartialEq, Debug, Clone)] -pub enum PropValue<'a> { - Expr(Expr<'a>), - Pat(Pat<'a>), - Method(PropMethod<'a>), -} - -impl<'a> From> for crate::expr::PropValue<'a> { - fn from(other: PropValue<'a>) -> Self { - match other { - PropValue::Expr(inner) => Self::Expr(inner.into()), - PropValue::Pat(inner) => Self::Pat(inner.into()), - PropValue::Method(inner) => Self::Expr(crate::expr::Expr::Func(inner.into())), - } - } +pub enum PropValue { + Expr(Expr), + Pat(Pat), + Method(PropMethod), } -impl<'a> Node for PropValue<'a> { +impl Node for PropValue { fn loc(&self) -> SourceLocation { match self { PropValue::Expr(inner) => inner.loc(), @@ -590,28 +423,18 @@ impl<'a> Node for PropValue<'a> { /// An operation that takes one argument #[derive(PartialEq, Debug, Clone)] -pub struct UnaryExpr<'a> { - pub operator: UnaryOp<'a>, - pub argument: Box>, +pub struct UnaryExpr { + pub operator: UnaryOp, + pub argument: Box>, } -impl<'a> UnaryExpr<'a> { +impl UnaryExpr { pub fn prefix(&self) -> bool { self.operator.loc() < self.argument.loc() } } -impl<'a> From> for crate::expr::UnaryExpr<'a> { - fn from(other: UnaryExpr<'a>) -> Self { - Self { - prefix: other.prefix(), - operator: other.operator.into(), - argument: Box::new(From::from(*other.argument)), - } - } -} - -impl<'a> Node for UnaryExpr<'a> { +impl Node for UnaryExpr { fn loc(&self) -> SourceLocation { let (start, end) = if self.prefix() { (self.operator.loc().start, self.argument.loc().end) @@ -624,29 +447,18 @@ impl<'a> Node for UnaryExpr<'a> { /// Increment or decrementing a value #[derive(PartialEq, Debug, Clone)] -pub struct UpdateExpr<'a> { - pub operator: UpdateOp<'a>, - pub argument: Box>, +pub struct UpdateExpr { + pub operator: UpdateOp, + pub argument: Box>, } -impl<'a> UpdateExpr<'a> { +impl UpdateExpr { pub fn prefix(&self) -> bool { self.operator.loc().start < self.argument.loc().start } } -impl<'a> From> for crate::expr::UpdateExpr<'a> { - fn from(other: UpdateExpr<'a>) -> Self { - let ret = Self { - prefix: other.prefix(), - operator: other.operator.into(), - argument: Box::new(From::from(*other.argument)), - }; - ret - } -} - -impl<'a> Node for UpdateExpr<'a> { +impl Node for UpdateExpr { fn loc(&self) -> SourceLocation { let op = self.operator.loc(); let arg = self.argument.loc(); @@ -666,23 +478,13 @@ impl<'a> Node for UpdateExpr<'a> { /// An operation that requires 2 arguments #[derive(PartialEq, Debug, Clone)] -pub struct BinaryExpr<'a> { - pub operator: BinaryOp<'a>, - pub left: Box>, - pub right: Box>, -} - -impl<'a> From> for crate::expr::BinaryExpr<'a> { - fn from(other: BinaryExpr<'a>) -> Self { - Self { - operator: other.operator.into(), - left: Box::new(From::from(*other.left)), - right: Box::new(From::from(*other.right)), - } - } +pub struct BinaryExpr { + pub operator: BinaryOp, + pub left: Box>, + pub right: Box>, } -impl<'a> Node for BinaryExpr<'a> { +impl Node for BinaryExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.left.loc().start, @@ -693,23 +495,13 @@ impl<'a> Node for BinaryExpr<'a> { /// An assignment or update + assignment operation #[derive(PartialEq, Debug, Clone)] -pub struct AssignExpr<'a> { - pub operator: AssignOp<'a>, - pub left: AssignLeft<'a>, - pub right: Box>, -} - -impl<'a> From> for crate::expr::AssignExpr<'a> { - fn from(other: AssignExpr<'a>) -> Self { - Self { - operator: other.operator.into(), - left: other.left.into(), - right: Box::new(From::from(*other.right)), - } - } +pub struct AssignExpr { + pub operator: AssignOp, + pub left: AssignLeft, + pub right: Box>, } -impl<'a> Node for AssignExpr<'a> { +impl Node for AssignExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.left.loc().start, @@ -719,15 +511,15 @@ impl<'a> Node for AssignExpr<'a> { } #[derive(PartialEq, Debug, Clone)] -pub struct AwaitExpr<'a> { - pub keyword: Slice<'a>, - pub expr: Expr<'a>, +pub struct AwaitExpr { + pub keyword: Await, + pub expr: Expr, } -impl<'a> Node for AwaitExpr<'a> { +impl Node for AwaitExpr { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.expr.loc().end, } } @@ -735,21 +527,12 @@ impl<'a> Node for AwaitExpr<'a> { /// The value being assigned to #[derive(PartialEq, Debug, Clone)] -pub enum AssignLeft<'a> { - Pat(Pat<'a>), - Expr(Box>), +pub enum AssignLeft { + Pat(Pat), + Expr(Box>), } -impl<'a> From> for crate::expr::AssignLeft<'a> { - fn from(other: AssignLeft<'a>) -> Self { - match other { - AssignLeft::Pat(inner) => Self::Pat(inner.into()), - AssignLeft::Expr(inner) => Self::Expr(Box::new(From::from(*inner))), - } - } -} - -impl<'a> Node for AssignLeft<'a> { +impl Node for AssignLeft { fn loc(&self) -> SourceLocation { match self { AssignLeft::Pat(inner) => inner.loc(), @@ -764,23 +547,13 @@ impl<'a> Node for AssignLeft<'a> { /// false || true /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct LogicalExpr<'a> { - pub operator: LogicalOp<'a>, - pub left: Box>, - pub right: Box>, +pub struct LogicalExpr { + pub operator: LogicalOp, + pub left: Box>, + pub right: Box>, } -impl<'a> From> for crate::expr::LogicalExpr<'a> { - fn from(other: LogicalExpr<'a>) -> Self { - Self { - operator: other.operator.into(), - left: Box::new(From::from(*other.left)), - right: Box::new(From::from(*other.right)), - } - } -} - -impl<'a> Node for LogicalExpr<'a> { +impl Node for LogicalExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.left.loc().start, @@ -795,30 +568,19 @@ impl<'a> Node for LogicalExpr<'a> { /// c.stuff; /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct MemberExpr<'a> { - pub object: Box>, - pub property: Box>, - pub indexer: MemberIndexer<'a>, -} - -impl<'a> From> for crate::expr::MemberExpr<'a> { - fn from(other: MemberExpr<'a>) -> Self { - let computed = other.computed(); - Self { - object: Box::new(From::from(*other.object)), - property: Box::new(From::from(*other.property)), - computed, - } - } +pub struct MemberExpr { + pub object: Box>, + pub property: Box>, + pub indexer: MemberIndexer, } -impl<'a> MemberExpr<'a> { +impl MemberExpr { pub fn computed(&self) -> bool { matches!(self.indexer, MemberIndexer::Computed { .. }) } } -impl<'a> Node for MemberExpr<'a> { +impl Node for MemberExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.object.loc().start, @@ -832,24 +594,24 @@ impl<'a> Node for MemberExpr<'a> { } #[derive(PartialEq, Debug, Clone)] -pub enum MemberIndexer<'a> { - Period(Slice<'a>), +pub enum MemberIndexer { + Period(Period), Computed { - open_bracket: Slice<'a>, - close_bracket: Slice<'a>, + open_bracket: OpenBracket, + close_bracket: CloseBracket, }, } -impl<'a> Node for MemberIndexer<'a> { +impl Node for MemberIndexer { fn loc(&self) -> SourceLocation { match self { - MemberIndexer::Period(inner) => inner.loc, + MemberIndexer::Period(inner) => inner.loc(), MemberIndexer::Computed { open_bracket, close_bracket, } => SourceLocation { - start: open_bracket.loc.start, - end: close_bracket.loc.end, + start: open_bracket.start(), + end: close_bracket.end(), }, } } @@ -860,25 +622,15 @@ impl<'a> Node for MemberIndexer<'a> { /// var a = true ? 'stuff' : 'things'; /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ConditionalExpr<'a> { - pub test: Box>, - pub question_mark: Slice<'a>, - pub alternate: Box>, - pub colon: Slice<'a>, - pub consequent: Box>, -} - -impl<'a> From> for crate::expr::ConditionalExpr<'a> { - fn from(other: ConditionalExpr<'a>) -> Self { - Self { - test: Box::new(From::from(*other.test)), - alternate: Box::new(From::from(*other.alternate)), - consequent: Box::new(From::from(*other.consequent)), - } - } +pub struct ConditionalExpr { + pub test: Box>, + pub question_mark: QuestionMark, + pub alternate: Box>, + pub colon: Colon, + pub consequent: Box>, } -impl<'a> Node for ConditionalExpr<'a> { +impl Node for ConditionalExpr { fn loc(&self) -> SourceLocation { let start = self.test.loc().start; let end = self.alternate.loc().end; @@ -891,27 +643,18 @@ impl<'a> Node for ConditionalExpr<'a> { /// Math.random() /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct CallExpr<'a> { - pub callee: Box>, - pub open_paren: Slice<'a>, - pub arguments: Vec>>, - pub close_paren: Slice<'a>, +pub struct CallExpr { + pub callee: Box>, + pub open_paren: OpenParen, + pub arguments: Vec>>, + pub close_paren: CloseParen, } -impl<'a> From> for crate::expr::CallExpr<'a> { - fn from(other: CallExpr<'a>) -> Self { - Self { - callee: Box::new(From::from(*other.callee)), - arguments: other.arguments.into_iter().map(|e| e.item.into()).collect(), - } - } -} - -impl<'a> Node for CallExpr<'a> { +impl Node for CallExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.callee.loc().start, - end: self.close_paren.loc.end, + end: self.close_paren.end(), } } } @@ -921,43 +664,34 @@ impl<'a> Node for CallExpr<'a> { /// new Uint8Array(32); /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct NewExpr<'a> { - pub keyword: Slice<'a>, - pub callee: Box>, - pub open_paren: Option>, - pub arguments: Vec>>, - pub close_paren: Option>, +pub struct NewExpr { + pub keyword: New, + pub callee: Box>, + pub open_paren: Option, + pub arguments: Vec>>, + pub close_paren: Option, } -impl<'a> From> for crate::expr::NewExpr<'a> { - fn from(other: NewExpr<'a>) -> Self { - Self { - callee: Box::new(From::from(*other.callee)), - arguments: other.arguments.into_iter().map(|e| e.item.into()).collect(), - } - } -} - -impl<'a> Node for NewExpr<'a> { +impl Node for NewExpr { fn loc(&self) -> SourceLocation { let end = if let Some(close) = &self.close_paren { - close.loc.end + close.end() } else if let Some(last) = self.arguments.last() { last.loc().end } else { self.callee.loc().end }; SourceLocation { - start: self.callee.loc().start, + start: self.keyword.start(), end: end, } } } /// A collection of `Exprs` separated by commas -pub type SequenceExpr<'a> = Vec>>; +pub type SequenceExpr = Vec>>; -impl<'a> Node for SequenceExpr<'a> { +impl Node for SequenceExpr { fn loc(&self) -> SourceLocation { let first_loc = if let Some(first) = self.first() { first.loc() @@ -977,31 +711,31 @@ impl<'a> Node for SequenceExpr<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct ArrowParamPlaceHolder<'a> { +pub struct ArrowParamPlaceHolder { // async keyword - pub keyword: Option>, - pub open_paren: Option>, - pub args: Vec>>, - pub close_paren: Option>, + pub keyword: Option, + pub open_paren: Option, + pub args: Vec>>, + pub close_paren: Option, } -impl<'a> Node for ArrowParamPlaceHolder<'a> { +impl Node for ArrowParamPlaceHolder { fn loc(&self) -> SourceLocation { let start = if let Some(keyword) = &self.keyword { - keyword.loc.start + keyword.start() } else if let Some(open) = &self.open_paren { - open.loc.start + open.start() } else if let Some(arg) = self.args.first() { arg.loc().start } else { - Position { line: 0, column: 0 } + crate::spanned::Position { line: 0, column: 0 } }; let end = if let Some(close) = &self.close_paren { - close.loc.end + close.end() } else if let Some(arg) = self.args.last() { arg.loc().end } else { - Position { line: 0, column: 0 } + crate::spanned::Position { line: 0, column: 0 } }; SourceLocation { start, end } } @@ -1015,34 +749,22 @@ impl<'a> Node for ArrowParamPlaceHolder<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ArrowFuncExpr<'a> { - pub keyword: Option>, - pub star: Option>, - pub open_paren: Option>, - pub params: Vec>>, - pub close_paren: Option>, - pub arrow: Slice<'a>, - pub body: ArrowFuncBody<'a>, -} - -impl<'a> From> for crate::expr::ArrowFuncExpr<'a> { - fn from(other: ArrowFuncExpr<'a>) -> Self { - let expression = matches!(&other.body, ArrowFuncBody::Expr(_)); - Self { - id: None, - params: other.params.into_iter().map(|e| e.item.into()).collect(), - body: other.body.into(), - expression, - generator: other.star.is_some(), - is_async: other.keyword.is_some(), - } - } +pub struct ArrowFuncExpr { + pub keyword: Option, + pub star: Option, + pub open_paren: Option, + pub params: Vec>>, + pub close_paren: Option, + pub arrow: FatArrow, + pub body: ArrowFuncBody, } -impl<'a> Node for ArrowFuncExpr<'a> { +impl Node for ArrowFuncExpr { fn loc(&self) -> SourceLocation { - let start = if let Some(slice) = &self.open_paren { - slice.loc.start + let start = if let Some(keyword) = &self.keyword { + keyword.start() + } else if let Some(slice) = &self.open_paren { + slice.start() } else if let Some(first) = self.params.first() { first.loc().start } else { @@ -1057,21 +779,12 @@ impl<'a> Node for ArrowFuncExpr<'a> { /// The body portion of an arrow function can be either an expression or a block of statements #[derive(PartialEq, Debug, Clone)] -pub enum ArrowFuncBody<'a> { - FuncBody(FuncBody<'a>), - Expr(Box>), -} - -impl<'a> From> for crate::expr::ArrowFuncBody<'a> { - fn from(other: ArrowFuncBody<'a>) -> Self { - match other { - ArrowFuncBody::FuncBody(inner) => Self::FuncBody(inner.into()), - ArrowFuncBody::Expr(inner) => Self::Expr(Box::new(From::from(*inner))), - } - } +pub enum ArrowFuncBody { + FuncBody(FuncBody), + Expr(Box>), } -impl<'a> Node for ArrowFuncBody<'a> { +impl Node for ArrowFuncBody { fn loc(&self) -> SourceLocation { match self { ArrowFuncBody::FuncBody(inner) => inner.loc(), @@ -1089,30 +802,21 @@ impl<'a> Node for ArrowFuncBody<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct YieldExpr<'a> { - pub keyword: Slice<'a>, - pub argument: Option>>, - pub star: Option>, +pub struct YieldExpr { + pub keyword: Yield, + pub argument: Option>>, + pub star: Option, } -impl<'a> From> for crate::expr::YieldExpr<'a> { - fn from(other: YieldExpr<'a>) -> Self { - Self { - argument: other.argument.map(|e| Box::new(From::from(*e))), - delegate: other.star.is_some(), - } - } -} - -impl<'a> Node for YieldExpr<'a> { +impl Node for YieldExpr { fn loc(&self) -> SourceLocation { let end = if let Some(arg) = &self.argument { arg.loc().end } else { - self.keyword.loc.end + self.keyword.end() }; SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end, } } @@ -1121,21 +825,12 @@ impl<'a> Node for YieldExpr<'a> { /// A Template literal preceded by a function identifier /// see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) for more details #[derive(PartialEq, Debug, Clone)] -pub struct TaggedTemplateExpr<'a> { - pub tag: Box>, - pub quasi: TemplateLit<'a>, +pub struct TaggedTemplateExpr { + pub tag: Box>, + pub quasi: TemplateLit, } -impl<'a> From> for crate::expr::TaggedTemplateExpr<'a> { - fn from(other: TaggedTemplateExpr<'a>) -> Self { - Self { - tag: Box::new(From::from(*other.tag)), - quasi: other.quasi.into(), - } - } -} - -impl<'a> Node for TaggedTemplateExpr<'a> { +impl Node for TaggedTemplateExpr { fn loc(&self) -> SourceLocation { SourceLocation { start: self.tag.loc().start, @@ -1149,21 +844,12 @@ impl<'a> Node for TaggedTemplateExpr<'a> { /// `I own ${0} birds`; /// ``` #[derive(Debug, Clone, PartialEq)] -pub struct TemplateLit<'a> { - pub quasis: Vec>, - pub expressions: Vec>, -} - -impl<'a> From> for crate::expr::TemplateLit<'a> { - fn from(other: TemplateLit<'a>) -> Self { - Self { - quasis: other.quasis.into_iter().map(From::from).collect(), - expressions: other.expressions.into_iter().map(From::from).collect(), - } - } +pub struct TemplateLit { + pub quasis: Vec>, + pub expressions: Vec>, } -impl<'a> Node for TemplateLit<'a> { +impl Node for TemplateLit { fn loc(&self) -> SourceLocation { let start = self .quasis @@ -1184,32 +870,30 @@ impl<'a> Node for TemplateLit<'a> { /// The text part of a `TemplateLiteral` #[derive(Debug, Clone, PartialEq)] -pub struct TemplateElement<'a> { - /// Raw quoted element - pub raw: Slice<'a>, - pub cooked: Slice<'a>, +pub struct TemplateElement { + pub open_quote: QuasiQuote, + pub content: Slice, + pub close_quote: QuasiQuote, } -impl<'a> From> for crate::expr::TemplateElement<'a> { - fn from(other: TemplateElement<'a>) -> Self { - let tail = other.is_tail(); - Self { - tail, - cooked: other.cooked.source, - raw: other.raw.source, - } +impl TemplateElement +where + T: AsRef, +{ + pub fn is_tail(&self) -> bool { + matches!( + self.open_quote, + QuasiQuote::BackTick(_) | QuasiQuote::CloseBrace(_) + ) && matches!(self.close_quote, QuasiQuote::BackTick(_)) } } -impl<'a> Node for TemplateElement<'a> { +impl Node for TemplateElement { fn loc(&self) -> SourceLocation { - self.raw.loc - } -} - -impl<'a> TemplateElement<'a> { - pub fn is_tail(&self) -> bool { - self.raw.source.starts_with(|c| c == '`' || c == '}') && self.raw.source.ends_with('`') + SourceLocation { + start: self.open_quote.start(), + end: self.close_quote.end(), + } } } @@ -1224,22 +908,13 @@ impl<'a> TemplateElement<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct MetaProp<'a> { - pub meta: Ident<'a>, - pub dot: Slice<'a>, - pub property: Ident<'a>, +pub struct MetaProp { + pub meta: Ident, + pub dot: Period, + pub property: Ident, } -impl<'a> From> for crate::expr::MetaProp<'a> { - fn from(other: MetaProp<'a>) -> Self { - Self { - meta: other.meta.into(), - property: other.property.into(), - } - } -} - -impl<'a> Node for MetaProp<'a> { +impl Node for MetaProp { fn loc(&self) -> SourceLocation { SourceLocation { start: self.meta.loc().start, @@ -1250,12 +925,12 @@ impl<'a> Node for MetaProp<'a> { /// A literal value #[derive(Debug, Clone, PartialEq)] -pub enum Lit<'a> { +pub enum Lit { /// `null` - Null(Slice<'a>), + Null(Null), /// `"string"` /// `'string'` - String(StringLit<'a>), + String(StringLit), /// `0` /// `0.0` /// `.0` @@ -1264,38 +939,74 @@ pub enum Lit<'a> { /// `0xf` /// `0o7` /// `0b1` - Number(Slice<'a>), + Number(Slice), /// `true` /// `false` - Boolean(Slice<'a>), + Boolean(Boolean), /// `/.+/g` - RegEx(RegEx<'a>), + RegEx(RegEx), /// ```js /// `I have ${0} apples` /// ``` - Template(TemplateLit<'a>), -} - -impl<'a> From> for crate::expr::Lit<'a> { - fn from(other: Lit<'a>) -> Self { - match other { - Lit::Null(_inner) => Self::Null, - Lit::String(inner) => Self::String(inner.into()), - Lit::Number(inner) => Self::Number(inner.source), - Lit::Boolean(inner) => Self::Boolean(inner.source == "true"), - Lit::RegEx(inner) => Self::RegEx(inner.into()), - Lit::Template(inner) => Self::Template(inner.into()), + Template(TemplateLit), +} + +impl Lit { + pub fn new_true(line: u32, column: u32) -> Self { + Self::Boolean(Boolean::new_true(line, column)) + } + + pub fn new_false(line: u32, column: u32) -> Self { + Self::Boolean(Boolean::new_false(line, column)) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Boolean { + True(True), + False(False), +} + +impl Boolean { + pub fn new_true(line: u32, column: u32) -> Self { + Self::True(crate::spanned::Position::new(line, column).into()) + } + + pub fn new_false(line: u32, column: u32) -> Self { + Self::False(crate::spanned::Position::new(line, column).into()) + } +} + +impl Token for Boolean { + fn as_str(&self) -> &str { + match self { + Boolean::True(inner) => inner.as_str(), + Boolean::False(inner) => inner.as_str(), + } + } + + fn start(&self) -> super::Position { + match self { + Boolean::True(inner) => inner.start(), + Boolean::False(inner) => inner.start(), + } + } + + fn end(&self) -> super::Position { + match self { + Boolean::True(inner) => inner.end(), + Boolean::False(inner) => inner.end(), } } } -impl<'a> Node for Lit<'a> { +impl Node for Lit { fn loc(&self) -> SourceLocation { match self { - Lit::Null(inner) => inner.loc, + Lit::Null(inner) => inner.loc(), Lit::String(inner) => inner.loc(), Lit::Number(inner) => inner.loc, - Lit::Boolean(inner) => inner.loc, + Lit::Boolean(inner) => inner.loc(), Lit::RegEx(inner) => inner.loc(), Lit::Template(inner) => inner.loc(), } @@ -1303,101 +1014,74 @@ impl<'a> Node for Lit<'a> { } #[derive(PartialEq, Debug, Clone)] -pub struct StringLit<'a> { - pub open_quote: Slice<'a>, - pub content: Slice<'a>, - pub close_quote: Slice<'a>, +pub struct StringLit { + pub open_quote: Quote, + pub content: Slice, + pub close_quote: Quote, } -impl<'a> From> for crate::expr::StringLit<'a> { - fn from(other: StringLit<'a>) -> Self { - if other.open_quote.source == "\"" { - Self::Double(other.content.source) - } else { - Self::Single(other.content.source) - } - } -} - -impl<'a> Node for StringLit<'a> { +impl Node for StringLit { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_quote.loc.start, - end: self.close_quote.loc.end, + start: self.open_quote.start(), + end: self.close_quote.end(), } } } -impl<'a> StringLit<'a> { - pub fn inner_matches(&self, o: &str) -> bool { - self.content.source == o - } -} /// A regular expression literal #[derive(PartialEq, Debug, Clone)] -pub struct RegEx<'a> { - pub open_slash: Slice<'a>, - pub pattern: Slice<'a>, - pub close_slash: Slice<'a>, - pub flags: Option>, +pub struct RegEx { + pub open_slash: ForwardSlash, + pub pattern: Slice, + pub close_slash: ForwardSlash, + pub flags: Option>, } -impl<'a> From> for crate::expr::RegEx<'a> { - fn from(other: RegEx<'a>) -> Self { - Self { - pattern: other.pattern.source, - flags: other - .flags - .map(|f| f.source) - .unwrap_or_else(|| Cow::Borrowed("")), - } - } -} - -impl<'a> Node for RegEx<'a> { +impl Node for RegEx { fn loc(&self) -> SourceLocation { let end = if let Some(flags) = &self.flags { flags.loc.end } else { - self.close_slash.loc.end + self.close_slash.end() }; SourceLocation { - start: self.open_slash.loc.start, + start: self.open_slash.start(), end, } } } #[derive(Debug, Clone, PartialEq)] -pub struct WrappedExpr<'a> { - pub open_paren: Slice<'a>, - pub expr: Expr<'a>, - pub close_paren: Slice<'a>, +pub struct WrappedExpr { + pub open_paren: OpenParen, + pub expr: Expr, + pub close_paren: CloseParen, } -impl<'a> Node for WrappedExpr<'a> { +impl Node for WrappedExpr { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_paren.loc.start, - end: self.close_paren.loc.end, + start: self.open_paren.start(), + end: self.close_paren.end(), } } } #[derive(Debug, Clone, PartialEq)] -pub struct SequenceExprEntry<'a> { - pub expr: Expr<'a>, - pub comma: Option>, +pub struct SequenceExprEntry { + pub expr: Expr, + pub comma: Option, } -impl<'a> SequenceExprEntry<'a> { - pub fn no_comma(expr: Expr<'a>) -> Self { +impl SequenceExprEntry { + pub fn no_comma(expr: Expr) -> Self { Self { expr, comma: None } } } -impl<'a> From> for FuncArgEntry<'a> { - fn from(other: SequenceExprEntry<'a>) -> Self { +impl From> for FuncArgEntry { + fn from(other: SequenceExprEntry) -> Self { Self { value: FuncArg::Expr(other.expr), comma: other.comma, @@ -1405,20 +1089,14 @@ impl<'a> From> for FuncArgEntry<'a> { } } -impl<'a> Node for SequenceExprEntry<'a> { +impl Node for SequenceExprEntry { fn loc(&self) -> SourceLocation { if let Some(comma) = &self.comma { return SourceLocation { start: self.expr.loc().start, - end: comma.loc.end, + end: comma.end(), }; } self.expr.loc() } } - -impl<'a> From> for crate::expr::Expr<'a> { - fn from(other: SequenceExprEntry<'a>) -> Self { - other.expr.into() - } -} diff --git a/src/spanned/mod.rs b/src/spanned/mod.rs index 5439749..80d7096 100644 --- a/src/spanned/mod.rs +++ b/src/spanned/mod.rs @@ -1,49 +1,59 @@ -use std::borrow::Cow; - +mod convert; pub mod decl; pub mod expr; pub mod pat; pub mod stmt; +pub mod tokens; use decl::Decl; use expr::{Expr, Lit, Prop}; use pat::Pat; use stmt::Stmt; -use self::pat::RestPat; +use crate::SourceText; + +use self::{ + pat::RestPat, + tokens::{ + AssignOp, Asterisk, Async, CloseBrace, CloseParen, Comma, Const, Extends, Function, Let, + OpenBrace, OpenParen, Semicolon, Token, Var, + }, +}; pub trait Node { fn loc(&self) -> SourceLocation; } #[derive(Debug, Clone, PartialEq)] -pub struct Ident<'a> { - pub slice: Slice<'a>, +pub struct Ident { + pub slice: Slice, } -impl<'a> Node for Ident<'a> { - fn loc(&self) -> SourceLocation { - self.slice.loc +impl Ident +where + T: AsRef, +{ + pub fn new_from_source(source: T, line: u32, start_col: u32) -> Self { + let len = source.as_ref().len() as u32; + Slice::new(source, line, start_col, line, start_col + len).into() } } -impl<'a> From> for crate::Ident<'a> { - fn from(other: Ident<'a>) -> Self { - Self { - name: other.slice.source, - } +impl Node for Ident { + fn loc(&self) -> SourceLocation { + self.slice.loc } } -impl<'a> From> for Ident<'a> { - fn from(slice: Slice<'a>) -> Self { +impl From> for Ident { + fn from(slice: Slice) -> Self { Self { slice } } } -impl<'a> Ident<'a> { - pub fn name(&self) -> Cow<'a, str> { - self.slice.source.clone() +impl Ident { + pub fn name(&self) -> &T { + &self.slice.source.0 } } @@ -53,23 +63,14 @@ impl<'a> Ident<'a> { /// with a flag denoting if the representation is /// a ES6 Mod or a Script. #[derive(Debug, Clone, PartialEq)] -pub enum Program<'a> { +pub enum Program { /// An ES6 Mod - Mod(Vec>), + Mod(Vec>), /// Not an ES6 Mod - Script(Vec>), -} - -impl<'a> From> for crate::Program<'a> { - fn from(other: Program<'a>) -> Self { - match other { - Program::Mod(inner) => Self::Mod(inner.into_iter().map(From::from).collect()), - Program::Script(inner) => Self::Script(inner.into_iter().map(From::from).collect()), - } - } + Script(Vec>), } -impl<'a> Node for Program<'a> { +impl Node for Program { fn loc(&self) -> SourceLocation { match self { Self::Mod(inner) => inner.loc(), @@ -78,16 +79,16 @@ impl<'a> Node for Program<'a> { } } -impl<'a> Program<'a> { - pub fn module(parts: Vec>) -> Self { +impl Program { + pub fn module(parts: Vec>) -> Self { Program::Mod(parts) } - pub fn script(parts: Vec>) -> Self { + pub fn script(parts: Vec>) -> Self { Program::Script(parts) } } -impl<'a> Node for Vec> { +impl Node for Vec> { fn loc(&self) -> SourceLocation { let start = self .first() @@ -104,26 +105,16 @@ impl<'a> Node for Vec> { /// A single part of a Javascript program. /// This will be either a Directive, Decl or a Stmt #[derive(Debug, Clone, PartialEq)] -pub enum ProgramPart<'a> { +pub enum ProgramPart { /// A Directive like `'use strict';` - Dir(Dir<'a>), + Dir(Dir), /// A variable, function or module declaration - Decl(Decl<'a>), + Decl(Decl), /// Any other kind of statement - Stmt(Stmt<'a>), + Stmt(Stmt), } -impl<'a> From> for crate::ProgramPart<'a> { - fn from(other: ProgramPart<'a>) -> Self { - match other { - ProgramPart::Dir(inner) => Self::Dir(inner.into()), - ProgramPart::Decl(inner) => Self::Decl(inner.into()), - ProgramPart::Stmt(inner) => Self::Stmt(inner.into()), - } - } -} - -impl<'a> Node for ProgramPart<'a> { +impl Node for ProgramPart { fn loc(&self) -> SourceLocation { match self { Self::Dir(inner) => inner.loc(), @@ -133,11 +124,11 @@ impl<'a> Node for ProgramPart<'a> { } } -impl<'a> ProgramPart<'a> { - pub fn decl(inner: Decl<'a>) -> Self { +impl ProgramPart { + pub fn decl(inner: Decl) -> Self { ProgramPart::Decl(inner) } - pub fn stmt(inner: Stmt<'a>) -> Self { + pub fn stmt(inner: Stmt) -> Self { ProgramPart::Stmt(inner) } } @@ -145,24 +136,22 @@ impl<'a> ProgramPart<'a> { /// pretty much always `'use strict'`, this can appear at the /// top of a file or function #[derive(Debug, Clone, PartialEq)] -pub struct Dir<'a> { - pub expr: Lit<'a>, - pub dir: Cow<'a, str>, - pub semi_colon: Option>, -} - -impl<'a> From> for crate::Dir<'a> { - fn from(other: Dir<'a>) -> Self { - Self { - expr: other.expr.into(), - dir: other.dir, - } - } +pub struct Dir { + pub expr: Lit, + pub dir: SourceText, + pub semi_colon: Option, } -impl<'a> Node for Dir<'a> { +impl Node for Dir { fn loc(&self) -> SourceLocation { - self.expr.loc() + let expr_loc = self.expr.loc(); + if let Some(semi) = &self.semi_colon { + return SourceLocation { + start: expr_loc.start, + end: semi.end(), + }; + } + expr_loc } } @@ -177,18 +166,18 @@ impl<'a> Node for Dir<'a> { /// let y = function q() {} /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct Func<'a> { - pub keyword: Slice<'a>, - pub id: Option>, - pub open_paren: Slice<'a>, - pub params: Vec>>, - pub close_paren: Slice<'a>, - pub body: FuncBody<'a>, - pub star: Option>, - pub keyword_async: Option>, -} - -impl<'a> Func<'a> { +pub struct Func { + pub keyword: Function, + pub id: Option>, + pub open_paren: OpenParen, + pub params: Vec>>, + pub close_paren: CloseParen, + pub body: FuncBody, + pub star: Option, + pub keyword_async: Option, +} + +impl Func { pub fn is_async(&self) -> bool { self.keyword_async.is_some() } @@ -197,52 +186,30 @@ impl<'a> Func<'a> { } } -impl<'a> From> for crate::Func<'a> { - fn from(other: Func<'a>) -> Self { - Self { - generator: other.generator(), - is_async: other.is_async(), - id: other.id.map(From::from), - params: other - .params - .into_iter() - .map(|e| From::from(e.item)) - .collect(), - body: other.body.into(), - } - } -} - -impl<'a> Node for Func<'a> { +impl Node for Func { fn loc(&self) -> SourceLocation { - let start = if let Some(keyword) = &self.keyword_async { - keyword.loc.start + let start = if let Some(keyword) = self.keyword_async { + keyword.start() } else { - self.keyword.loc.start + self.keyword.start() }; - let end = self.body.close_brace.loc.end.clone(); + let end = self.body.close_brace.end(); SourceLocation { start, end } } } #[derive(Debug, Clone, PartialEq)] -pub struct FuncArgEntry<'a> { - pub value: FuncArg<'a>, - pub comma: Option>, +pub struct FuncArgEntry { + pub value: FuncArg, + pub comma: Option, } -impl<'a> From> for crate::FuncArg<'a> { - fn from(other: FuncArgEntry<'a>) -> Self { - other.value.into() - } -} - -impl<'a> Node for FuncArgEntry<'a> { +impl Node for FuncArgEntry { fn loc(&self) -> SourceLocation { if let Some(comma) = &self.comma { return SourceLocation { start: self.value.loc().start, - end: comma.loc.end, + end: comma.end(), }; } self.value.loc() @@ -251,25 +218,13 @@ impl<'a> Node for FuncArgEntry<'a> { /// A single function argument from a function signature #[derive(Debug, Clone, PartialEq)] -pub enum FuncArg<'a> { - Expr(Expr<'a>), - Pat(Pat<'a>), - Rest(Box>), -} - -impl<'a> From> for crate::FuncArg<'a> { - fn from(other: FuncArg<'a>) -> Self { - match other { - FuncArg::Expr(inner) => Self::Expr(inner.into()), - FuncArg::Pat(inner) => Self::Pat(inner.into()), - FuncArg::Rest(inner) => { - Self::Pat(crate::pat::Pat::RestElement(Box::new(inner.pat.into()))) - } - } - } +pub enum FuncArg { + Expr(Expr), + Pat(Pat), + Rest(Box>), } -impl<'a> Node for FuncArg<'a> { +impl Node for FuncArg { fn loc(&self) -> SourceLocation { match self { FuncArg::Expr(inner) => inner.loc(), @@ -281,23 +236,17 @@ impl<'a> Node for FuncArg<'a> { /// The block statement that makes up the function's body #[derive(Debug, Clone, PartialEq)] -pub struct FuncBody<'a> { - pub open_brace: Slice<'a>, - pub stmts: Vec>, - pub close_brace: Slice<'a>, -} - -impl<'a> From> for crate::FuncBody<'a> { - fn from(other: FuncBody<'a>) -> Self { - Self(other.stmts.into_iter().map(From::from).collect()) - } +pub struct FuncBody { + pub open_brace: OpenBrace, + pub stmts: Vec>, + pub close_brace: CloseBrace, } -impl<'a> Node for FuncBody<'a> { +impl Node for FuncBody { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } @@ -329,334 +278,91 @@ impl<'a> Node for FuncBody<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct Class<'a> { - pub keyword: Slice<'a>, - pub id: Option>, - pub super_class: Option>, - pub body: ClassBody<'a>, +pub struct Class { + pub keyword: tokens::Class, + pub id: Option>, + pub super_class: Option>, + pub body: ClassBody, } -impl<'a> From> for crate::Class<'a> { - fn from(other: Class<'a>) -> Self { - Self { - id: other.id.map(From::from), - super_class: other.super_class.map(|e| Box::new(From::from(e.expr))), - body: other.body.into(), - } - } -} - -impl<'a> Node for Class<'a> { +impl Node for Class { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, - end: self.body.close_brace.loc.end, + start: self.keyword.start(), + end: self.body.close_brace.end(), } } } #[derive(PartialEq, Debug, Clone)] -pub struct SuperClass<'a> { - pub keyword_extends: Slice<'a>, - pub expr: Expr<'a>, +pub struct SuperClass { + pub keyword_extends: Extends, + pub expr: Expr, } #[derive(Debug, Clone, PartialEq)] -pub struct ClassBody<'a> { - pub open_brace: Slice<'a>, - pub props: Vec>, - pub close_brace: Slice<'a>, -} - -impl<'a> From> for crate::ClassBody<'a> { - fn from(other: ClassBody<'a>) -> Self { - Self(other.props.into_iter().map(From::from).collect()) - } +pub struct ClassBody { + pub open_brace: OpenBrace, + pub props: Vec>, + pub close_brace: CloseBrace, } -impl<'a> Node for ClassBody<'a> { +impl Node for ClassBody { fn loc(&self) -> SourceLocation { - let start = self.open_brace.loc.start; - let end = self.close_brace.loc.end; + let start = self.open_brace.start(); + let end = self.close_brace.end(); SourceLocation { start, end } } } /// The kind of variable being defined (`var`/`let`/`const`) #[derive(Debug, Clone, PartialEq)] -pub enum VarKind<'a> { - Var(Option>), - Let(Slice<'a>), - Const(Slice<'a>), -} - -impl<'a> From> for crate::VarKind { - fn from(other: VarKind<'a>) -> Self { - match other { - VarKind::Var(_) => Self::Var, - VarKind::Let(_) => Self::Let, - VarKind::Const(_) => Self::Const, - } - } +pub enum VarKind { + Var(Option), + Let(Let), + Const(Const), } -impl<'a> Node for VarKind<'a> { +impl Node for VarKind { fn loc(&self) -> SourceLocation { match self { - VarKind::Var(Some(slice)) => slice.loc, - VarKind::Let(slice) => slice.loc, - VarKind::Const(slice) => slice.loc, + VarKind::Var(Some(tok)) => tok.loc(), + VarKind::Let(tok) => tok.loc(), + VarKind::Const(tok) => tok.loc(), _ => SourceLocation::zero(), } } } -impl<'a> VarKind<'a> { +impl VarKind { pub fn is_var(&self) -> bool { matches!(self, VarKind::Var(_)) } -} - -/// The available operators for assignment Exprs -#[derive(Debug, Clone, PartialEq)] -pub enum AssignOp<'a> { - Equal(Slice<'a>), - PlusEqual(Slice<'a>), - MinusEqual(Slice<'a>), - TimesEqual(Slice<'a>), - DivEqual(Slice<'a>), - ModEqual(Slice<'a>), - LeftShiftEqual(Slice<'a>), - RightShiftEqual(Slice<'a>), - UnsignedRightShiftEqual(Slice<'a>), - OrEqual(Slice<'a>), - XOrEqual(Slice<'a>), - AndEqual(Slice<'a>), - PowerOfEqual(Slice<'a>), -} - -impl<'a> From> for crate::AssignOp { - fn from(other: AssignOp<'a>) -> Self { - match other { - AssignOp::Equal(_) => Self::Equal, - AssignOp::PlusEqual(_) => Self::PlusEqual, - AssignOp::MinusEqual(_) => Self::MinusEqual, - AssignOp::TimesEqual(_) => Self::TimesEqual, - AssignOp::DivEqual(_) => Self::DivEqual, - AssignOp::ModEqual(_) => Self::ModEqual, - AssignOp::LeftShiftEqual(_) => Self::LeftShiftEqual, - AssignOp::RightShiftEqual(_) => Self::RightShiftEqual, - AssignOp::UnsignedRightShiftEqual(_) => Self::UnsignedRightShiftEqual, - AssignOp::OrEqual(_) => Self::OrEqual, - AssignOp::XOrEqual(_) => Self::XOrEqual, - AssignOp::AndEqual(_) => Self::AndEqual, - AssignOp::PowerOfEqual(_) => Self::PowerOfEqual, - } - } -} - -impl<'a> Node for AssignOp<'a> { - fn loc(&self) -> SourceLocation { + pub const fn len(&self) -> u32 { match self { - AssignOp::Equal(slice) => slice.loc, - AssignOp::PlusEqual(slice) => slice.loc, - AssignOp::MinusEqual(slice) => slice.loc, - AssignOp::TimesEqual(slice) => slice.loc, - AssignOp::DivEqual(slice) => slice.loc, - AssignOp::ModEqual(slice) => slice.loc, - AssignOp::LeftShiftEqual(slice) => slice.loc, - AssignOp::RightShiftEqual(slice) => slice.loc, - AssignOp::UnsignedRightShiftEqual(slice) => slice.loc, - AssignOp::OrEqual(slice) => slice.loc, - AssignOp::XOrEqual(slice) => slice.loc, - AssignOp::AndEqual(slice) => slice.loc, - AssignOp::PowerOfEqual(slice) => slice.loc, + VarKind::Var(Some(_)) => 3, + VarKind::Var(None) => 0, + VarKind::Let(_) => 3, + VarKind::Const(_) => 4, } } } -/// The available logical operators #[derive(Debug, Clone, PartialEq)] -pub enum LogicalOp<'a> { - Or(Slice<'a>), - And(Slice<'a>), -} - -impl<'a> From> for crate::LogicalOp { - fn from(other: LogicalOp<'a>) -> Self { - match other { - LogicalOp::Or(_) => Self::Or, - LogicalOp::And(_) => Self::And, - } - } -} - -impl<'a> Node for LogicalOp<'a> { - fn loc(&self) -> SourceLocation { - match self { - LogicalOp::Or(slice) => slice.loc, - LogicalOp::And(slice) => slice.loc, - } - } -} - -/// The available operations for `Binary` Exprs -#[derive(Debug, Clone, PartialEq)] -pub enum BinaryOp<'a> { - Equal(Slice<'a>), - NotEqual(Slice<'a>), - StrictEqual(Slice<'a>), - StrictNotEqual(Slice<'a>), - LessThan(Slice<'a>), - GreaterThan(Slice<'a>), - LessThanEqual(Slice<'a>), - GreaterThanEqual(Slice<'a>), - LeftShift(Slice<'a>), - RightShift(Slice<'a>), - UnsignedRightShift(Slice<'a>), - Plus(Slice<'a>), - Minus(Slice<'a>), - Times(Slice<'a>), - Over(Slice<'a>), - Mod(Slice<'a>), - Or(Slice<'a>), - XOr(Slice<'a>), - And(Slice<'a>), - In(Slice<'a>), - InstanceOf(Slice<'a>), - PowerOf(Slice<'a>), -} - -impl<'a> From> for crate::BinaryOp { - fn from(other: BinaryOp<'a>) -> Self { - match other { - BinaryOp::Equal(_) => Self::Equal, - BinaryOp::NotEqual(_) => Self::NotEqual, - BinaryOp::StrictEqual(_) => Self::StrictEqual, - BinaryOp::StrictNotEqual(_) => Self::StrictNotEqual, - BinaryOp::LessThan(_) => Self::LessThan, - BinaryOp::GreaterThan(_) => Self::GreaterThan, - BinaryOp::LessThanEqual(_) => Self::LessThanEqual, - BinaryOp::GreaterThanEqual(_) => Self::GreaterThanEqual, - BinaryOp::LeftShift(_) => Self::LeftShift, - BinaryOp::RightShift(_) => Self::RightShift, - BinaryOp::UnsignedRightShift(_) => Self::UnsignedRightShift, - BinaryOp::Plus(_) => Self::Plus, - BinaryOp::Minus(_) => Self::Minus, - BinaryOp::Times(_) => Self::Times, - BinaryOp::Over(_) => Self::Over, - BinaryOp::Mod(_) => Self::Mod, - BinaryOp::Or(_) => Self::Or, - BinaryOp::XOr(_) => Self::XOr, - BinaryOp::And(_) => Self::And, - BinaryOp::In(_) => Self::In, - BinaryOp::InstanceOf(_) => Self::InstanceOf, - BinaryOp::PowerOf(_) => Self::PowerOf, - } - } -} - -impl<'a> Node for BinaryOp<'a> { - fn loc(&self) -> SourceLocation { - match self { - BinaryOp::Equal(slice) => slice.loc, - BinaryOp::NotEqual(slice) => slice.loc, - BinaryOp::StrictEqual(slice) => slice.loc, - BinaryOp::StrictNotEqual(slice) => slice.loc, - BinaryOp::LessThan(slice) => slice.loc, - BinaryOp::GreaterThan(slice) => slice.loc, - BinaryOp::LessThanEqual(slice) => slice.loc, - BinaryOp::GreaterThanEqual(slice) => slice.loc, - BinaryOp::LeftShift(slice) => slice.loc, - BinaryOp::RightShift(slice) => slice.loc, - BinaryOp::UnsignedRightShift(slice) => slice.loc, - BinaryOp::Plus(slice) => slice.loc, - BinaryOp::Minus(slice) => slice.loc, - BinaryOp::Times(slice) => slice.loc, - BinaryOp::Over(slice) => slice.loc, - BinaryOp::Mod(slice) => slice.loc, - BinaryOp::Or(slice) => slice.loc, - BinaryOp::XOr(slice) => slice.loc, - BinaryOp::And(slice) => slice.loc, - BinaryOp::In(slice) => slice.loc, - BinaryOp::InstanceOf(slice) => slice.loc, - BinaryOp::PowerOf(slice) => slice.loc, - } - } -} - -/// `++` or `--` -#[derive(Debug, Clone, PartialEq)] -pub enum UpdateOp<'a> { - Increment(Slice<'a>), - Decrement(Slice<'a>), -} - -impl<'a> From> for crate::UpdateOp { - fn from(other: UpdateOp<'a>) -> Self { - match other { - UpdateOp::Increment(_) => Self::Increment, - UpdateOp::Decrement(_) => Self::Decrement, - } - } -} - -impl<'a> Node for UpdateOp<'a> { - fn loc(&self) -> SourceLocation { - match self { - UpdateOp::Increment(slice) => slice.loc, - UpdateOp::Decrement(slice) => slice.loc, - } - } -} - -/// The allowed operators for an Expr -/// to be `Unary` -#[derive(Debug, Clone, PartialEq)] -pub enum UnaryOp<'a> { - Minus(Slice<'a>), - Plus(Slice<'a>), - Not(Slice<'a>), - Tilde(Slice<'a>), - TypeOf(Slice<'a>), - Void(Slice<'a>), - Delete(Slice<'a>), -} - -impl<'a> From> for crate::UnaryOp { - fn from(other: UnaryOp<'a>) -> Self { - match other { - UnaryOp::Minus(_) => Self::Minus, - UnaryOp::Plus(_) => Self::Plus, - UnaryOp::Not(_) => Self::Not, - UnaryOp::Tilde(_) => Self::Tilde, - UnaryOp::TypeOf(_) => Self::TypeOf, - UnaryOp::Void(_) => Self::Void, - UnaryOp::Delete(_) => Self::Delete, - } - } +pub struct Slice { + pub source: SourceText, + pub loc: SourceLocation, } -impl<'a> Node for UnaryOp<'a> { - fn loc(&self) -> SourceLocation { - match self { - UnaryOp::Minus(slice) => slice.loc, - UnaryOp::Plus(slice) => slice.loc, - UnaryOp::Not(slice) => slice.loc, - UnaryOp::Tilde(slice) => slice.loc, - UnaryOp::TypeOf(slice) => slice.loc, - UnaryOp::Void(slice) => slice.loc, - UnaryOp::Delete(slice) => slice.loc, +impl Slice { + pub fn new(source: T, start_line: u32, start_col: u32, end_line: u32, end_column: u32) -> Self { + Self { + source: SourceText(source), + loc: SourceLocation::new(start_line, start_col, end_line, end_column), } } } -#[derive(Debug, Clone, PartialEq)] -pub struct Slice<'a> { - pub source: Cow<'a, str>, - pub loc: SourceLocation, -} - #[derive(Debug, Clone, PartialEq, Copy)] pub struct SourceLocation { pub start: Position, @@ -664,7 +370,7 @@ pub struct SourceLocation { } impl SourceLocation { - pub fn new(start_line: usize, start_column: usize, end_line: usize, end_column: usize) -> Self { + pub fn new(start_line: u32, start_column: u32, end_line: u32, end_column: u32) -> Self { Self { start: Position { line: start_line, @@ -693,8 +399,14 @@ impl core::cmp::PartialOrd for SourceLocation { #[derive(Debug, Clone, PartialEq, Copy)] pub struct Position { - pub line: usize, - pub column: usize, + pub line: u32, + pub column: u32, +} + +impl Position { + pub fn new(line: u32, column: u32) -> Self { + Self { line, column } + } } impl std::cmp::PartialOrd for Position { @@ -729,27 +441,49 @@ impl std::ops::Sub for Position { } } +impl std::ops::Add for Position { + type Output = Self; + + fn add(self, rhs: u32) -> Self::Output { + Self { + line: self.line, + column: self.column + rhs, + } + } +} + +impl std::ops::Sub for Position { + type Output = Self; + + fn sub(self, rhs: u32) -> Self::Output { + Self { + line: self.line, + column: self.column - rhs, + } + } +} + #[derive(Debug, Clone, PartialEq)] -pub struct ListEntry<'a, T> { - pub item: T, - pub comma: Option>, +pub struct ListEntry { + pub item: Item, + pub comma: Option, } -impl<'a, T> ListEntry<'a, T> { - pub fn no_comma(item: T) -> Self { +impl ListEntry { + pub fn no_comma(item: Item) -> Self { Self { item, comma: None } } } -impl<'a, T> Node for ListEntry<'a, T> +impl Node for ListEntry where - T: Node, + Item: Node, { fn loc(&self) -> SourceLocation { if let Some(comma) = &self.comma { return SourceLocation { start: self.item.loc().start, - end: comma.loc.end, + end: comma.end(), }; } self.item.loc() diff --git a/src/spanned/pat.rs b/src/spanned/pat.rs index 92992e0..5b9e965 100644 --- a/src/spanned/pat.rs +++ b/src/spanned/pat.rs @@ -1,29 +1,19 @@ use crate::spanned::expr::{Expr, Prop}; use crate::spanned::Ident; -use super::{AssignOp, ListEntry, Node, Slice, SourceLocation}; +use super::tokens::{CloseBrace, CloseBracket, Comma, Ellipsis, OpenBrace, OpenBracket, Token}; +use super::{AssignOp, ListEntry, Node, SourceLocation}; /// All of the different ways you can declare an identifier /// and/or value #[derive(Debug, Clone, PartialEq)] -pub enum Pat<'a> { - Ident(Ident<'a>), - Obj(ObjPat<'a>), - Array(ArrayPat<'a>), - Assign(AssignPat<'a>), +pub enum Pat { + Ident(Ident), + Obj(ObjPat), + Array(ArrayPat), + Assign(AssignPat), } -impl<'a> From> for crate::pat::Pat<'a> { - fn from(other: Pat<'a>) -> Self { - match other { - Pat::Ident(inner) => Self::Ident(inner.into()), - Pat::Obj(inner) => Self::Obj(inner.into()), - Pat::Array(inner) => Self::Array(inner.into()), - Pat::Assign(inner) => Self::Assign(inner.into()), - } - } -} - -impl<'a> Node for Pat<'a> { +impl Node for Pat { fn loc(&self) -> super::SourceLocation { match self { Pat::Ident(inner) => inner.loc(), @@ -35,63 +25,35 @@ impl<'a> Node for Pat<'a> { } #[derive(Debug, Clone, PartialEq)] -pub struct ArrayPat<'a> { - pub open_bracket: Slice<'a>, - pub elements: Vec>>>, - pub close_bracket: Slice<'a>, +pub struct ArrayPat { + pub open_bracket: OpenBracket, + pub elements: Vec>>>, + pub close_bracket: CloseBracket, } -impl<'a> Node for ArrayPat<'a> { +impl Node for ArrayPat { fn loc(&self) -> super::SourceLocation { SourceLocation { - start: self.open_bracket.loc.start, - end: self.close_bracket.loc.end, + start: self.open_bracket.start(), + end: self.close_bracket.end(), } } } -impl<'a> From> for Vec>> { - fn from(other: ArrayPat<'a>) -> Self { - other - .elements - .into_iter() - .map(|e| e.item.map(Into::into)) - .collect() - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct ArrayElement<'a> { - pub part: Option>, - pub comma: Option>, -} - -impl<'a> From> for Option> { - fn from(other: ArrayElement<'a>) -> Self { - other.part.map(From::from) - } +pub struct ArrayElement { + pub part: Option>, + pub comma: Option, } #[derive(PartialEq, Debug, Clone)] -pub enum ArrayPatPart<'a> { - Pat(Pat<'a>), - Expr(Expr<'a>), - Rest(RestPat<'a>), +pub enum ArrayPatPart { + Pat(Pat), + Expr(Expr), + Rest(RestPat), } -impl<'a> From> for crate::pat::ArrayPatPart<'a> { - fn from(other: ArrayPatPart<'a>) -> Self { - match other { - ArrayPatPart::Pat(inner) => Self::Pat(inner.into()), - ArrayPatPart::Expr(inner) => Self::Expr(inner.into()), - ArrayPatPart::Rest(inner) => { - Self::Pat(crate::pat::Pat::RestElement(Box::new(inner.pat.into()))) - } - } - } -} - -impl<'a> Node for ArrayPatPart<'a> { +impl Node for ArrayPatPart { fn loc(&self) -> SourceLocation { match self { ArrayPatPart::Pat(inner) => inner.loc(), @@ -101,39 +63,33 @@ impl<'a> Node for ArrayPatPart<'a> { } } -type ObjEntry<'a> = ListEntry<'a, ObjPatPart<'a>>; +type ObjEntry = ListEntry>; /// similar to an `ObjectExpr` #[derive(PartialEq, Debug, Clone)] -pub struct ObjPat<'a> { - pub open_brace: Slice<'a>, - pub props: Vec>, - pub close_brace: Slice<'a>, +pub struct ObjPat { + pub open_brace: OpenBrace, + pub props: Vec>, + pub close_brace: CloseBrace, } -impl<'a> Node for ObjPat<'a> { +impl Node for ObjPat { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } -impl<'a> From> for crate::pat::ObjPat<'a> { - fn from(other: ObjPat<'a>) -> Self { - other.props.into_iter().map(|e| e.item.into()).collect() - } -} - /// A single part of an ObjectPat #[derive(PartialEq, Debug, Clone)] -pub enum ObjPatPart<'a> { - Assign(Prop<'a>), - Rest(Box>), +pub enum ObjPatPart { + Assign(Prop), + Rest(Box>), } -impl<'a> Node for ObjPatPart<'a> { +impl Node for ObjPatPart { fn loc(&self) -> SourceLocation { match self { ObjPatPart::Assign(prop) => prop.loc(), @@ -142,25 +98,16 @@ impl<'a> Node for ObjPatPart<'a> { } } -impl<'a> From> for crate::pat::ObjPatPart<'a> { - fn from(other: ObjPatPart<'a>) -> Self { - match other { - ObjPatPart::Assign(prop) => Self::Assign(prop.into()), - ObjPatPart::Rest(inner) => Self::Rest(Box::new(From::from(inner.pat))), - } - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct RestPat<'a> { - pub dots: Slice<'a>, - pub pat: Pat<'a>, +pub struct RestPat { + pub dots: Ellipsis, + pub pat: Pat, } -impl<'a> Node for RestPat<'a> { +impl Node for RestPat { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.dots.loc.start, + start: self.dots.start(), end: self.pat.loc().end, } } @@ -168,13 +115,13 @@ impl<'a> Node for RestPat<'a> { /// An assignment as a pattern #[derive(Debug, Clone, PartialEq)] -pub struct AssignPat<'a> { - pub left: Box>, - pub operator: AssignOp<'a>, - pub right: Box>, +pub struct AssignPat { + pub left: Box>, + pub operator: AssignOp, + pub right: Box>, } -impl<'a> Node for AssignPat<'a> { +impl Node for AssignPat { fn loc(&self) -> SourceLocation { SourceLocation { start: self.left.loc().start, @@ -182,12 +129,3 @@ impl<'a> Node for AssignPat<'a> { } } } - -impl<'a> From> for crate::pat::AssignPat<'a> { - fn from(other: AssignPat<'a>) -> Self { - Self { - left: Box::new(From::from(*other.left)), - right: Box::new(From::from(*other.right)), - } - } -} diff --git a/src/spanned/stmt.rs b/src/spanned/stmt.rs index e7e09fc..b3dee92 100644 --- a/src/spanned/stmt.rs +++ b/src/spanned/stmt.rs @@ -5,24 +5,29 @@ use crate::spanned::VarKind; use crate::spanned::{Ident, ProgramPart}; use super::decl::VarDecls; -use super::{ListEntry, Node, Slice, SourceLocation}; +use super::tokens::{ + Break, Catch, CloseBrace, CloseParen, Colon, Continue, Debugger, Do, Else, Finally, For, If, + In, Of, OpenBrace, OpenParen, Return, Semicolon, Switch, SwitchCaseKeyword, Throw, Token, Try, + While, With, +}; +use super::{ListEntry, Node, SourceLocation}; /// A slightly more granular part of an es program than ProgramPart #[derive(Debug, Clone, PartialEq)] -pub enum Stmt<'a> { +pub enum Stmt { /// Any expression Expr { - expr: Expr<'a>, - semi_colon: Option>, + expr: Expr, + semi_colon: Option, }, /// A collection of program parts wrapped in curly braces - Block(BlockStmt<'a>), + Block(BlockStmt), /// A single semi-colon - Empty(Slice<'a>), + Empty(Semicolon), /// The contextual keyword `debugger` Debugger { - keyword: Slice<'a>, - semi_colon: Option>, + keyword: Debugger, + semi_colon: Option, }, /// A with statement, this puts one object at the top of /// the identifier search tree. @@ -37,7 +42,7 @@ pub enum Stmt<'a> { /// } /// //rand !== 0 /// ``` - With(WithStmt<'a>), + With(WithStmt), /// A return statement /// ```js /// function thing() { @@ -47,9 +52,9 @@ pub enum Stmt<'a> { /// return; /// } Return { - keyword: Slice<'a>, - value: Option>, - semi_colon: Option>, + keyword: Return, + value: Option>, + semi_colon: Option, }, /// A labeled statement /// ```js @@ -57,7 +62,7 @@ pub enum Stmt<'a> { /// break label; /// } /// ``` - Labeled(LabeledStmt<'a>), + Labeled(LabeledStmt), /// A break statement /// ```js /// label: { @@ -68,9 +73,9 @@ pub enum Stmt<'a> { /// } /// ``` Break { - keyword: Slice<'a>, - label: Option>, - semi_colon: Option>, + keyword: Break, + label: Option>, + semi_colon: Option, }, /// A short circuit continuation of a loop /// ```js @@ -83,19 +88,19 @@ pub enum Stmt<'a> { /// } /// ``` Continue { - keyword: Slice<'a>, - label: Option>, - semi_colon: Option>, + keyword: Continue, + label: Option>, + semi_colon: Option, }, /// An if statement /// ```js /// if (1 < 2) { - /// console.log('Always true'); + /// console.log(Tlways true'); /// } else { /// console.log('Never true'); /// } /// ``` - If(IfStmt<'a>), + If(IfStmt), /// A switch statement /// ```js /// switch (Math.floor(Math.random()) * 10) { @@ -110,7 +115,7 @@ pub enum Stmt<'a> { /// return true; /// } /// ``` - Switch(SwitchStmt<'a>), + Switch(SwitchStmt), /// A statement that throws an error /// ```js /// function error() { @@ -122,9 +127,9 @@ pub enum Stmt<'a> { /// } /// ``` Throw { - keyword: Slice<'a>, - expr: Expr<'a>, - semi_colon: Option>, + keyword: Throw, + expr: Expr, + semi_colon: Option, }, /// A try/catch block /// ```js @@ -136,7 +141,7 @@ pub enum Stmt<'a> { /// /// } /// ``` - Try(TryStmt<'a>), + Try(TryStmt), /// A while loop /// ```js /// while (false) { @@ -151,14 +156,14 @@ pub enum Stmt<'a> { /// } /// } /// ``` - While(WhileStmt<'a>), + While(WhileStmt), /// A while loop that executes its body first /// ```js /// do { - /// console.log('at least once') + /// console.log(Tt least once') /// } while (Math.floor(Math.random() * 100) < 75) /// ``` - DoWhile(DoWhileStmt<'a>), + DoWhile(DoWhileStmt), /// A "c-style" for loop /// ```js /// for (var i = 0; i < 100; i++) console.log(i); @@ -166,7 +171,7 @@ pub enum Stmt<'a> { /// console.log('forever!'); /// } /// ``` - For(ForStmt<'a>), + For(ForStmt), /// A for in statement, this kind of for statement /// will extract each key from an indexable thing /// ```js @@ -179,7 +184,7 @@ pub enum Stmt<'a> { /// } /// //prints a, b /// ``` - ForIn(ForInStmt<'a>), + ForIn(ForInStmt), /// A for of statement, this kind of for statement /// will extract the value from a generator or iterator /// ```js @@ -188,71 +193,43 @@ pub enum Stmt<'a> { /// } /// //prints 2, 3, 4, 5, 6 /// ``` - ForOf(ForOfStmt<'a>), + ForOf(ForOfStmt), /// A var statement /// ```js /// var x; /// var x, y = 'huh?'; /// ``` Var { - decls: VarDecls<'a>, - semi_colon: Option>, + decls: VarDecls, + semi_colon: Option, }, } -impl<'a> From> for crate::stmt::Stmt<'a> { - fn from(other: Stmt<'a>) -> Self { - match other { - Stmt::Expr { expr, .. } => Self::Expr(expr.into()), - Stmt::Block(inner) => Self::Block(inner.into()), - Stmt::Empty(_) => Self::Empty, - Stmt::Debugger { .. } => Self::Debugger, - Stmt::With(inner) => Self::With(inner.into()), - Stmt::Return { value, .. } => Self::Return(value.map(From::from)), - Stmt::Labeled(inner) => Self::Labeled(inner.into()), - Stmt::Break { label, .. } => Self::Break(label.map(From::from)), - Stmt::Continue { label, .. } => Self::Continue(label.map(From::from)), - Stmt::If(inner) => Self::If(inner.into()), - Stmt::Switch(inner) => Self::Switch(inner.into()), - Stmt::Throw { expr, .. } => Self::Throw(expr.into()), - Stmt::Try(inner) => Self::Try(inner.into()), - Stmt::While(inner) => Self::While(inner.into()), - Stmt::DoWhile(inner) => Self::DoWhile(inner.into()), - Stmt::For(inner) => Self::For(inner.into()), - Stmt::ForIn(inner) => Self::ForIn(inner.into()), - Stmt::ForOf(inner) => Self::ForOf(inner.into()), - Stmt::Var { decls, .. } => { - Self::Var(decls.decls.into_iter().map(|e| e.item.into()).collect()) - } - } - } -} - -impl<'a> Node for Stmt<'a> { - fn loc(&self) -> super::SourceLocation { +impl Node for Stmt { + fn loc(&self) -> SourceLocation { match self { Stmt::Expr { expr, semi_colon } => { if let Some(semi) = semi_colon { return SourceLocation { start: expr.loc().start, - end: semi.loc.end, + end: semi.end(), }; } expr.loc() } Stmt::Block(inner) => inner.loc(), - Stmt::Empty(inner) => inner.loc, + Stmt::Empty(inner) => inner.loc(), Stmt::Debugger { keyword, semi_colon, } => { if let Some(semi) = semi_colon { return SourceLocation { - start: keyword.loc.start, - end: semi.loc.end, + start: keyword.start(), + end: semi.end(), }; } - keyword.loc + keyword.loc() } Stmt::With(inner) => inner.loc(), Stmt::Return { @@ -262,17 +239,17 @@ impl<'a> Node for Stmt<'a> { } => { if let Some(semi) = semi_colon { return SourceLocation { - start: keyword.loc.start, - end: semi.loc.end, + start: keyword.start(), + end: semi.end(), }; } if let Some(value) = value { return SourceLocation { - start: keyword.loc.start, + start: keyword.start(), end: value.loc().end, }; } - keyword.loc + keyword.loc() } Stmt::Labeled(inner) => inner.loc(), Stmt::Break { @@ -282,17 +259,17 @@ impl<'a> Node for Stmt<'a> { } => { if let Some(semi_colon) = semi_colon { return SourceLocation { - start: keyword.loc.start, - end: semi_colon.loc.end, + start: keyword.start(), + end: semi_colon.end(), }; } if let Some(label) = label { return SourceLocation { - start: keyword.loc.start, + start: keyword.start(), end: label.loc().end, }; } - keyword.loc + keyword.loc() } Stmt::Continue { keyword, @@ -301,17 +278,17 @@ impl<'a> Node for Stmt<'a> { } => { if let Some(semi_colon) = semi_colon { return SourceLocation { - start: keyword.loc.start, - end: semi_colon.loc.end, + start: keyword.end(), + end: semi_colon.end(), }; } if let Some(label) = label { return SourceLocation { - start: keyword.loc.start, + start: keyword.start(), end: label.loc().end, }; } - keyword.loc + keyword.loc() } Stmt::If(inner) => inner.loc(), Stmt::Switch(inner) => inner.loc(), @@ -322,12 +299,12 @@ impl<'a> Node for Stmt<'a> { } => { if let Some(semi) = semi_colon { return SourceLocation { - start: keyword.loc.start, - end: semi.loc.end, + start: keyword.start(), + end: semi.end(), }; } SourceLocation { - start: keyword.loc.start, + start: keyword.start(), end: expr.loc().end, } } @@ -341,7 +318,7 @@ impl<'a> Node for Stmt<'a> { if let Some(semi) = semi_colon { return SourceLocation { start: decls.loc().start, - end: semi.loc.end, + end: semi.end(), }; } decls.loc() @@ -364,32 +341,22 @@ impl<'a> Node for Stmt<'a> { /// //rand !== 0 /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct WithStmt<'a> { - pub keyword: Slice<'a>, - pub open_paren: Slice<'a>, - pub object: Expr<'a>, - pub close_paren: Slice<'a>, - pub body: Box>, +pub struct WithStmt { + pub keyword: With, + pub open_paren: OpenParen, + pub object: Expr, + pub close_paren: CloseParen, + pub body: Box>, } -impl<'a> Node for WithStmt<'a> { +impl Node for WithStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } } - -impl<'a> From> for crate::stmt::WithStmt<'a> { - fn from(other: WithStmt<'a>) -> Self { - Self { - object: other.object.into(), - body: Box::new(From::from(*other.body)), - } - } -} - /// A labeled statement /// ```js /// label: { @@ -400,13 +367,13 @@ impl<'a> From> for crate::stmt::WithStmt<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct LabeledStmt<'a> { - pub label: Ident<'a>, - pub colon: Slice<'a>, - pub body: Box>, +pub struct LabeledStmt { + pub label: Ident, + pub colon: Colon, + pub body: Box>, } -impl<'a> Node for LabeledStmt<'a> { +impl Node for LabeledStmt { fn loc(&self) -> SourceLocation { SourceLocation { start: self.label.loc().start, @@ -415,36 +382,27 @@ impl<'a> Node for LabeledStmt<'a> { } } -impl<'a> From> for crate::stmt::LabeledStmt<'a> { - fn from(other: LabeledStmt<'a>) -> Self { - Self { - label: other.label.into(), - body: Box::new(From::from(*other.body)), - } - } -} - /// An if statement /// ```js /// if (1 < 2) { -/// console.log('Always true'); +/// console.log(Tlways true'); /// } else { /// console.log('Never true'); /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct IfStmt<'a> { - pub keyword: Slice<'a>, - pub open_paren: Slice<'a>, - pub test: Expr<'a>, - pub close_paren: Slice<'a>, - pub consequent: Box>, - pub alternate: Option>>, +pub struct IfStmt { + pub keyword: If, + pub open_paren: OpenParen, + pub test: Expr, + pub close_paren: CloseParen, + pub consequent: Box>, + pub alternate: Option>>, } -impl<'a> Node for IfStmt<'a> { +impl Node for IfStmt { fn loc(&self) -> SourceLocation { - let start = self.keyword.loc.start; + let start = self.keyword.start(); let end = if let Some(alt) = &self.alternate { alt.loc().end } else { @@ -454,26 +412,16 @@ impl<'a> Node for IfStmt<'a> { } } -impl<'a> From> for crate::stmt::IfStmt<'a> { - fn from(other: IfStmt<'a>) -> Self { - Self { - test: other.test.into(), - consequent: Box::new(From::from(*other.consequent)), - alternate: other.alternate.map(|s| Box::new(From::from(s.body))), - } - } -} - #[derive(PartialEq, Debug, Clone)] -pub struct ElseStmt<'a> { - pub keyword: Slice<'a>, - pub body: Stmt<'a>, +pub struct ElseStmt { + pub keyword: Else, + pub body: Stmt, } -impl<'a> Node for ElseStmt<'a> { +impl Node for ElseStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } @@ -494,85 +442,61 @@ impl<'a> Node for ElseStmt<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct SwitchStmt<'a> { - pub keyword: Slice<'a>, - pub open_paren: Slice<'a>, - pub discriminant: Expr<'a>, - pub close_paren: Slice<'a>, - pub open_brace: Slice<'a>, - pub cases: Vec>, - pub close_brace: Slice<'a>, +pub struct SwitchStmt { + pub keyword: Switch, + pub open_paren: OpenParen, + pub discriminant: Expr, + pub close_paren: CloseParen, + pub open_brace: OpenBrace, + pub cases: Vec>, + pub close_brace: CloseBrace, } -impl<'a> Node for SwitchStmt<'a> { +impl Node for SwitchStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, - end: self.close_paren.loc.end, - } - } -} - -impl<'a> From> for crate::stmt::SwitchStmt<'a> { - fn from(other: SwitchStmt<'a>) -> Self { - Self { - discriminant: other.discriminant.into(), - cases: other.cases.into_iter().map(From::from).collect(), + start: self.keyword.start(), + end: self.close_paren.end(), } } } /// A single case part of a switch statement #[derive(Debug, Clone, PartialEq)] -pub struct SwitchCase<'a> { - pub keyword: Slice<'a>, - pub test: Option>, - pub colon: Slice<'a>, - pub consequent: Vec>, +pub struct SwitchCase { + pub keyword: SwitchCaseKeyword, + pub test: Option>, + pub colon: Colon, + pub consequent: Vec>, } -impl<'a> Node for SwitchCase<'a> { +impl Node for SwitchCase { fn loc(&self) -> SourceLocation { let end = if let Some(last) = self.consequent.last() { last.loc().end } else { - self.colon.loc.end + self.colon.end() }; SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end, } } } -impl<'a> From> for crate::stmt::SwitchCase<'a> { - fn from(other: SwitchCase<'a>) -> Self { - Self { - test: other.test.map(From::from), - consequent: other.consequent.into_iter().map(From::from).collect(), - } - } -} - /// A collection of program parts wrapped in curly braces #[derive(Debug, Clone, PartialEq)] -pub struct BlockStmt<'a> { - pub open_brace: Slice<'a>, - pub stmts: Vec>, - pub close_brace: Slice<'a>, -} - -impl<'a> From> for crate::stmt::BlockStmt<'a> { - fn from(other: BlockStmt<'a>) -> Self { - Self(other.stmts.into_iter().map(From::from).collect()) - } +pub struct BlockStmt { + pub open_brace: OpenBrace, + pub stmts: Vec>, + pub close_brace: CloseBrace, } -impl<'a> Node for BlockStmt<'a> { +impl Node for BlockStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_brace.loc.start, - end: self.close_brace.loc.end, + start: self.open_brace.start(), + end: self.close_brace.end(), } } } @@ -588,14 +512,14 @@ impl<'a> Node for BlockStmt<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct TryStmt<'a> { - pub keyword: Slice<'a>, - pub block: BlockStmt<'a>, - pub handler: Option>, - pub finalizer: Option>, +pub struct TryStmt { + pub keyword: Try, + pub block: BlockStmt, + pub handler: Option>, + pub finalizer: Option>, } -impl<'a> Node for TryStmt<'a> { +impl Node for TryStmt { fn loc(&self) -> SourceLocation { let end = if let Some(finalizer) = &self.finalizer { finalizer.loc().end @@ -605,85 +529,60 @@ impl<'a> Node for TryStmt<'a> { self.block.loc().end }; SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end, } } } -impl<'a> From> for crate::stmt::TryStmt<'a> { - fn from(other: TryStmt<'a>) -> Self { - Self { - block: other.block.into(), - handler: other.handler.map(From::from), - finalizer: other.finalizer.map(From::from), - } - } -} - /// The error handling part of a `TryStmt` #[derive(Debug, Clone, PartialEq)] -pub struct CatchClause<'a> { - pub keyword: Slice<'a>, - pub param: Option>, - pub body: BlockStmt<'a>, +pub struct CatchClause { + pub keyword: Catch, + pub param: Option>, + pub body: BlockStmt, } -impl<'a> Node for CatchClause<'a> { +impl Node for CatchClause { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::CatchClause<'a> { - fn from(other: CatchClause<'a>) -> Self { - Self { - param: other.param.map(|a| a.param.into()), - body: other.body.into(), - } - } -} - #[derive(Debug, Clone, PartialEq)] -pub struct CatchArg<'a> { - pub open_paren: Slice<'a>, - pub param: Pat<'a>, - pub close_paren: Slice<'a>, +pub struct CatchArg { + pub open_paren: OpenParen, + pub param: Pat, + pub close_paren: CloseParen, } -impl<'a> Node for CatchArg<'a> { +impl Node for CatchArg { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.open_paren.loc.start, - end: self.close_paren.loc.end, + start: self.open_paren.start(), + end: self.close_paren.end(), } } } #[derive(Debug, Clone, PartialEq)] -pub struct FinallyClause<'a> { - pub keyword: Slice<'a>, - pub body: BlockStmt<'a>, +pub struct FinallyClause { + pub keyword: Finally, + pub body: BlockStmt, } -impl<'a> Node for FinallyClause<'a> { +impl Node for FinallyClause { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::BlockStmt<'a> { - fn from(other: FinallyClause<'a>) -> Self { - other.body.into() - } -} - /// A while loop /// ```js /// while (false) { @@ -699,63 +598,50 @@ impl<'a> From> for crate::stmt::BlockStmt<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct WhileStmt<'a> { - pub keyword: Slice<'a>, - pub open_paren: Slice<'a>, - pub test: Expr<'a>, - pub close_paren: Slice<'a>, - pub body: Box>, +pub struct WhileStmt { + pub keyword: While, + pub open_paren: OpenParen, + pub test: Expr, + pub close_paren: CloseParen, + pub body: Box>, } -impl<'a> Node for WhileStmt<'a> { +impl Node for WhileStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::WhileStmt<'a> { - fn from(other: WhileStmt<'a>) -> Self { - Self { - test: other.test.into(), - body: Box::new(From::from(*other.body)), - } - } -} - /// A while loop that executes its body first /// ```js /// do { -/// console.log('at least once') +/// console.log(Tt least once') /// } while (Math.floor(Math.random() * 100) < 75) /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct DoWhileStmt<'a> { - pub keyword_do: Slice<'a>, - pub body: Box>, - pub keyword_while: Slice<'a>, - pub open_paren: Slice<'a>, - pub test: Expr<'a>, - pub close_paren: Slice<'a>, - pub semi_colon: Option>, +pub struct DoWhileStmt { + pub keyword_do: Do, + pub body: Box>, + pub keyword_while: While, + pub open_paren: OpenParen, + pub test: Expr, + pub close_paren: CloseParen, + pub semi_colon: Option, } -impl<'a> Node for DoWhileStmt<'a> { +impl Node for DoWhileStmt { fn loc(&self) -> SourceLocation { + let end = self + .semi_colon + .map(|s| s.end()) + .unwrap_or_else(|| self.close_paren.end()) + + 1; SourceLocation { - start: self.keyword_do.loc.start, - end: self.close_paren.loc.end, - } - } -} - -impl<'a> From> for crate::stmt::DoWhileStmt<'a> { - fn from(other: DoWhileStmt<'a>) -> Self { - Self { - test: other.test.into(), - body: Box::new(From::from(*other.body)), + start: self.keyword_do.start(), + end, } } } @@ -768,49 +654,38 @@ impl<'a> From> for crate::stmt::DoWhileStmt<'a> { /// } /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ForStmt<'a> { - pub keyword: Slice<'a>, - pub open_paren: Slice<'a>, - pub init: Option>, - pub semi1: Slice<'a>, - pub test: Option>, - pub semi2: Slice<'a>, - pub update: Option>, - pub close_paren: Slice<'a>, - pub body: Box>, -} - -impl<'a> Node for ForStmt<'a> { +pub struct ForStmt { + pub keyword: For, + pub open_paren: OpenParen, + pub init: Option>, + pub semi1: Semicolon, + pub test: Option>, + pub semi2: Semicolon, + pub update: Option>, + pub close_paren: CloseParen, + pub body: Box>, +} + +impl Node for ForStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword.loc.start, + start: self.keyword.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::ForStmt<'a> { - fn from(other: ForStmt<'a>) -> Self { - Self { - init: other.init.map(From::from), - test: other.test.map(From::from), - update: other.update.map(From::from), - body: Box::new(From::from(*other.body)), - } - } -} - /// The left most triple of a for loops parenthetical /// ```js /// // vvvvvvvvv /// for (var i = 0;i < 100; i++) #[derive(Debug, Clone, PartialEq)] -pub enum LoopInit<'a> { - Variable(VarKind<'a>, Vec>>), - Expr(Expr<'a>), +pub enum LoopInit { + Variable(VarKind, Vec>>), + Expr(Expr), } -impl<'a> Node for LoopInit<'a> { +impl Node for LoopInit { fn loc(&self) -> SourceLocation { match self { LoopInit::Variable(kind, decls) => { @@ -828,18 +703,6 @@ impl<'a> Node for LoopInit<'a> { } } -impl<'a> From> for crate::stmt::LoopInit<'a> { - fn from(other: LoopInit<'a>) -> Self { - match other { - LoopInit::Expr(inner) => Self::Expr(inner.into()), - LoopInit::Variable(kind, decls) => Self::Variable( - kind.into(), - decls.into_iter().map(|e| e.item.into()).collect(), - ), - } - } -} - /// A for in statement, this kind of for statement /// will extract each key from an indexable thing /// ```js @@ -853,35 +716,25 @@ impl<'a> From> for crate::stmt::LoopInit<'a> { /// //prints a, b /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ForInStmt<'a> { - pub keyword_for: Slice<'a>, - pub open_paren: Slice<'a>, - pub left: LoopLeft<'a>, - pub keyword_in: Slice<'a>, - pub right: Expr<'a>, - pub close_paren: Slice<'a>, - pub body: Box>, +pub struct ForInStmt { + pub keyword_for: For, + pub open_paren: OpenParen, + pub left: LoopLeft, + pub keyword_in: In, + pub right: Expr, + pub close_paren: CloseParen, + pub body: Box>, } -impl<'a> Node for ForInStmt<'a> { +impl Node for ForInStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword_for.loc.start, + start: self.keyword_for.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::ForInStmt<'a> { - fn from(other: ForInStmt<'a>) -> Self { - Self { - left: other.left.into(), - right: other.right.into(), - body: Box::new(From::from(*other.body)), - } - } -} - /// A for of statement, this kind of for statement /// will extract the value from a generator or iterator /// ```js @@ -891,57 +744,36 @@ impl<'a> From> for crate::stmt::ForInStmt<'a> { /// //prints 2, 3, 4, 5, 6 /// ``` #[derive(PartialEq, Debug, Clone)] -pub struct ForOfStmt<'a> { - pub keyword_for: Slice<'a>, - pub open_paren: Slice<'a>, - pub left: LoopLeft<'a>, - pub keyword_of: Slice<'a>, - pub right: Expr<'a>, - pub close_paren: Slice<'a>, - pub body: Box>, +pub struct ForOfStmt { + pub keyword_for: For, + pub open_paren: OpenParen, + pub left: LoopLeft, + pub keyword_of: Of, + pub right: Expr, + pub close_paren: CloseParen, + pub body: Box>, pub is_await: bool, } -impl<'a> Node for ForOfStmt<'a> { +impl Node for ForOfStmt { fn loc(&self) -> SourceLocation { SourceLocation { - start: self.keyword_for.loc.start, + start: self.keyword_for.start(), end: self.body.loc().end, } } } -impl<'a> From> for crate::stmt::ForOfStmt<'a> { - fn from(other: ForOfStmt<'a>) -> Self { - Self { - left: other.left.into(), - right: other.right.into(), - body: Box::new(From::from(*other.body)), - is_await: other.is_await, - } - } -} - /// The values on the left hand side of the keyword /// in a for in or for of loop #[derive(Debug, Clone, PartialEq)] -pub enum LoopLeft<'a> { - Expr(Expr<'a>), - Variable(VarKind<'a>, VarDecl<'a>), - Pat(Pat<'a>), -} - -impl<'a> From> for crate::stmt::LoopLeft<'a> { - fn from(other: LoopLeft<'a>) -> Self { - match other { - LoopLeft::Expr(inner) => Self::Expr(inner.into()), - LoopLeft::Variable(kind, decl) => Self::Variable(kind.into(), decl.into()), - LoopLeft::Pat(inner) => Self::Pat(inner.into()), - } - } +pub enum LoopLeft { + Expr(Expr), + Variable(VarKind, VarDecl), + Pat(Pat), } -impl<'a> Node for LoopLeft<'a> { +impl Node for LoopLeft { fn loc(&self) -> SourceLocation { match self { LoopLeft::Expr(inner) => inner.loc(), diff --git a/src/spanned/tokens.rs b/src/spanned/tokens.rs new file mode 100644 index 0000000..be41d5d --- /dev/null +++ b/src/spanned/tokens.rs @@ -0,0 +1,444 @@ +//! This modules contains a collection of discrete tokens + +use crate::spanned::{Node, Position, SourceLocation}; + +macro_rules! impl_token { + ($what:ty, $s:expr) => { + impl Token for $what { + fn as_str(&self) -> &str { + $s + } + fn start(&self) -> Position { + self.0 + } + fn end(&self) -> Position { + self.0 + ($s.len() as u32) + } + } + impl std::convert::From for $what { + fn from(other: Position) -> Self { + Self(other) + } + } + impl std::convert::Into for $what { + fn into(self) -> Position { + self.0 + } + } + impl std::cmp::PartialEq for $what { + fn eq(&self, other: &Position) -> bool { + self.0 == *other + } + } + }; +} + +/// Defines a token struct and implements the Token trait for the newly defined type. +/// The output of this macro produces something like the following. +/// ```rust +/// # use resast::spanned::{Position, tokens::Token}; +/// #[derive(Debug, Clone, Copy, PartialEq)] +/// #[doc = "as"] +/// pub struct As(Position); +/// +/// impl Token for As { +/// fn as_str(&self) -> &str { +/// "as" +/// } +/// fn start(&self) -> Position { +/// self.0 +/// } +/// fn end(&self) -> Position { +/// self.0 + ("as".len() as u32) +/// } +/// } +/// impl std::convert::From for As { +/// fn from(other: Position) -> Self { +/// Self(other) +/// } +/// } +/// impl std::convert::Into for As { +/// fn into(self) -> Position { +/// self.0 +/// } +/// } +/// impl std::cmp::PartialEq for As { +/// fn eq(&self, other: &Position) -> bool { +/// self.0 == *other +/// } +/// } +/// ``` +macro_rules! define_token { + ($name:ident, $s:expr) => { + #[derive(Debug, Clone, Copy, PartialEq)] + #[doc = $s] + pub struct $name(Position); + impl_token!($name, $s); + }; +} + +pub trait Token { + fn as_str(&self) -> &str; + fn start(&self) -> Position; + fn end(&self) -> Position; +} + +impl Node for T +where + T: Token, +{ + fn loc(&self) -> SourceLocation { + SourceLocation { + start: self.start(), + end: self.end(), + } + } +} + +// Keywords +define_token!(As, "as"); +define_token!(Async, "async"); +define_token!(Await, "await"); +define_token!(Break, "break"); +define_token!(Case, "case"); +define_token!(Catch, "catch"); +define_token!(Class, "class"); +define_token!(Const, "const"); +define_token!(Continue, "continue"); +define_token!(Debugger, "debugger"); +define_token!(Default, "default"); +define_token!(Delete, "delete"); +define_token!(Do, "do"); +define_token!(Else, "else"); +define_token!(Export, "export"); +define_token!(Extends, "extends"); +define_token!(Finally, "finally"); +define_token!(From, "from"); +define_token!(Get, "get"); +define_token!(False, "false"); +define_token!(For, "for"); +define_token!(Function, "function"); +define_token!(If, "if"); +define_token!(Import, "import"); +define_token!(In, "in"); +define_token!(InstanceOf, "instanceof"); +define_token!(Let, "let"); +define_token!(New, "new"); +define_token!(Null, "null"); +define_token!(Of, "of"); +define_token!(Return, "return"); +define_token!(Set, "set"); +define_token!(Static, "static"); +define_token!(Super, "super"); +define_token!(Switch, "switch"); +define_token!(This, "this"); +define_token!(Throw, "throw"); +define_token!(True, "true"); +define_token!(Try, "try"); +define_token!(TypeOf, "typeof"); +define_token!(Var, "var"); +define_token!(Void, "void"); +define_token!(While, "while"); +define_token!(With, "with"); +define_token!(Yield, "yield"); + +// Punctuation +define_token!(Ampersand, "&"); +define_token!(AmpersandEqual, "&="); +define_token!(Asterisk, "*"); +define_token!(AsteriskEqual, "*="); +define_token!(BackTick, "`"); +define_token!(Bang, "!"); +define_token!(BangEqual, "!="); +define_token!(BangDoubleEqual, "!=="); +define_token!(Caret, "^"); +define_token!(CaretEqual, "^="); +define_token!(CloseParen, ")"); +define_token!(CloseBrace, "}"); +define_token!(CloseBracket, "]"); +define_token!(Colon, ":"); +define_token!(Comma, ","); +define_token!(DoubleAmpersand, "&&"); +define_token!(DoubleAsterisk, "**"); +define_token!(DoubleAsteriskEqual, "**="); +define_token!(DoubleEqual, "=="); +define_token!(DollarSignOpenBrace, "${"); +define_token!(DoubleGreaterThan, ">>"); +define_token!(DoubleGreaterThanEqual, ">>="); +define_token!(DoubleLessThan, "<<"); +define_token!(DoubleLessThanEqual, "<<="); +define_token!(DoublePipe, "||"); +define_token!(DoubleQuote, "\""); +define_token!(Ellipsis, "..."); +define_token!(Equal, "="); +define_token!(FatArrow, "=>"); +define_token!(ForwardSlash, "/"); +define_token!(ForwardSlashEqual, "/="); +define_token!(GreaterThan, ">"); +define_token!(GreaterThanEqual, ">="); +define_token!(LessThan, "<"); +define_token!(LessThanEqual, "<="); +define_token!(Minus, "-"); +define_token!(MinusEqual, "-="); +define_token!(OpenBrace, "{"); +define_token!(OpenBracket, "["); +define_token!(OpenParen, "("); +define_token!(Percent, "%"); +define_token!(PercentEqual, "%="); +define_token!(Period, "."); +define_token!(Pipe, "|"); +define_token!(PipeEqual, "|="); +define_token!(Plus, "+"); +define_token!(PlusEqual, "+="); +define_token!(QuestionMark, "?"); +define_token!(Semicolon, ";"); +define_token!(SingleQuote, "'"); +define_token!(Tilde, "~"); +define_token!(TripleEqual, "==="); +define_token!(TripleGreaterThan, ">>>"); +define_token!(TripleGreaterThanEqual, ">>>="); + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Quote { + Double(DoubleQuote), + Single(SingleQuote), +} + +impl Token for Quote { + fn as_str(&self) -> &str { + match self { + Quote::Double(inner) => inner.as_str(), + Quote::Single(inner) => inner.as_str(), + } + } + + fn start(&self) -> Position { + match self { + Quote::Double(inner) => inner.start(), + Quote::Single(inner) => inner.start(), + } + } + + fn end(&self) -> Position { + match self { + Quote::Double(inner) => inner.end(), + Quote::Single(inner) => inner.end(), + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum QuasiQuote { + BackTick(BackTick), + CloseBrace(CloseBrace), + OpenBrace(DollarSignOpenBrace), +} + +impl Token for QuasiQuote { + fn as_str(&self) -> &str { + match self { + Self::BackTick(inner) => inner.as_str(), + Self::CloseBrace(inner) => inner.as_str(), + Self::OpenBrace(inner) => inner.as_str(), + } + } + + fn start(&self) -> Position { + match self { + Self::BackTick(inner) => inner.start(), + Self::CloseBrace(inner) => inner.start(), + Self::OpenBrace(inner) => inner.start(), + } + } + + fn end(&self) -> Position { + match self { + Self::BackTick(inner) => inner.end(), + Self::CloseBrace(inner) => inner.end(), + Self::OpenBrace(inner) => inner.end(), + } + } +} + +/// The available operators for assignment Exprs +#[derive(Debug, Clone, PartialEq)] +pub enum AssignOp { + Equal(Equal), + PlusEqual(PlusEqual), + MinusEqual(MinusEqual), + TimesEqual(AsteriskEqual), + DivEqual(ForwardSlashEqual), + ModEqual(PercentEqual), + LeftShiftEqual(DoubleLessThanEqual), + RightShiftEqual(DoubleGreaterThanEqual), + UnsignedRightShiftEqual(TripleGreaterThanEqual), + OrEqual(PipeEqual), + XOrEqual(CaretEqual), + AndEqual(AmpersandEqual), + PowerOfEqual(DoubleAsteriskEqual), +} + +impl Node for AssignOp { + fn loc(&self) -> SourceLocation { + match self { + AssignOp::Equal(tok) => tok.loc(), + AssignOp::PlusEqual(tok) => tok.loc(), + AssignOp::MinusEqual(tok) => tok.loc(), + AssignOp::TimesEqual(tok) => tok.loc(), + AssignOp::DivEqual(tok) => tok.loc(), + AssignOp::ModEqual(tok) => tok.loc(), + AssignOp::LeftShiftEqual(tok) => tok.loc(), + AssignOp::RightShiftEqual(tok) => tok.loc(), + AssignOp::UnsignedRightShiftEqual(tok) => tok.loc(), + AssignOp::OrEqual(tok) => tok.loc(), + AssignOp::XOrEqual(tok) => tok.loc(), + AssignOp::AndEqual(tok) => tok.loc(), + AssignOp::PowerOfEqual(tok) => tok.loc(), + } + } +} + +/// The available logical operators +#[derive(Debug, Clone, PartialEq)] +pub enum LogicalOp { + Or(DoublePipe), + And(DoubleAmpersand), +} + +impl Node for LogicalOp { + fn loc(&self) -> SourceLocation { + match self { + LogicalOp::Or(tok) => tok.loc(), + LogicalOp::And(tok) => tok.loc(), + } + } +} + +/// The available operations for `Binary` Exprs +#[derive(Debug, Clone, PartialEq)] +pub enum BinaryOp { + Equal(DoubleEqual), + NotEqual(BangEqual), + StrictEqual(TripleEqual), + StrictNotEqual(BangDoubleEqual), + LessThan(LessThan), + GreaterThan(GreaterThan), + LessThanEqual(LessThanEqual), + GreaterThanEqual(GreaterThanEqual), + LeftShift(DoubleLessThan), + RightShift(DoubleGreaterThan), + UnsignedRightShift(TripleGreaterThan), + Plus(Plus), + Minus(Minus), + Times(Asterisk), + Over(ForwardSlash), + Mod(Percent), + Or(Pipe), + XOr(Caret), + And(Ampersand), + In(In), + InstanceOf(InstanceOf), + PowerOf(DoubleAsterisk), +} + +impl Node for BinaryOp { + fn loc(&self) -> SourceLocation { + match self { + BinaryOp::Equal(tok) => tok.loc(), + BinaryOp::NotEqual(tok) => tok.loc(), + BinaryOp::StrictEqual(tok) => tok.loc(), + BinaryOp::StrictNotEqual(tok) => tok.loc(), + BinaryOp::LessThan(tok) => tok.loc(), + BinaryOp::GreaterThan(tok) => tok.loc(), + BinaryOp::LessThanEqual(tok) => tok.loc(), + BinaryOp::GreaterThanEqual(tok) => tok.loc(), + BinaryOp::LeftShift(tok) => tok.loc(), + BinaryOp::RightShift(tok) => tok.loc(), + BinaryOp::UnsignedRightShift(tok) => tok.loc(), + BinaryOp::Plus(tok) => tok.loc(), + BinaryOp::Minus(tok) => tok.loc(), + BinaryOp::Times(tok) => tok.loc(), + BinaryOp::Over(tok) => tok.loc(), + BinaryOp::Mod(tok) => tok.loc(), + BinaryOp::Or(tok) => tok.loc(), + BinaryOp::XOr(tok) => tok.loc(), + BinaryOp::And(tok) => tok.loc(), + BinaryOp::In(tok) => tok.loc(), + BinaryOp::InstanceOf(tok) => tok.loc(), + BinaryOp::PowerOf(tok) => tok.loc(), + } + } +} +define_token!(DoublePlus, "++"); +define_token!(DoubleMinus, "--"); +/// `++` or `--` +#[derive(Debug, Clone, PartialEq)] +pub enum UpdateOp { + Increment(DoublePlus), + Decrement(DoubleMinus), +} + +impl Node for UpdateOp { + fn loc(&self) -> SourceLocation { + match self { + Self::Increment(tok) => tok.loc(), + Self::Decrement(tok) => tok.loc(), + } + } +} + +/// The allowed operators for an Expr +/// to be `Unary` +#[derive(Debug, Clone, PartialEq)] +pub enum UnaryOp { + Minus(Minus), + Plus(Plus), + Not(Bang), + Tilde(Tilde), + TypeOf(TypeOf), + Void(Void), + Delete(Delete), +} + +impl Node for UnaryOp { + fn loc(&self) -> SourceLocation { + match self { + Self::Minus(tok) => tok.loc(), + Self::Plus(tok) => tok.loc(), + Self::Not(tok) => tok.loc(), + Self::Tilde(tok) => tok.loc(), + Self::TypeOf(tok) => tok.loc(), + Self::Void(tok) => tok.loc(), + Self::Delete(tok) => tok.loc(), + } + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum SwitchCaseKeyword { + Case(Case), + Default(Default), +} + +impl Token for SwitchCaseKeyword { + fn as_str(&self) -> &str { + match self { + SwitchCaseKeyword::Case(inner) => inner.as_str(), + SwitchCaseKeyword::Default(inner) => inner.as_str(), + } + } + + fn start(&self) -> Position { + match self { + SwitchCaseKeyword::Case(inner) => inner.start(), + SwitchCaseKeyword::Default(inner) => inner.start(), + } + } + + fn end(&self) -> Position { + match self { + SwitchCaseKeyword::Case(inner) => inner.end(), + SwitchCaseKeyword::Default(inner) => inner.end(), + } + } +} diff --git a/src/stmt.rs b/src/stmt.rs index f289eca..6f265da 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -10,11 +10,11 @@ use crate::{Ident, ProgramPart}; derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum Stmt<'a> { +pub enum Stmt { /// Any expression - Expr(Expr<'a>), + Expr(Expr), /// A collection of program parts wrapped in curly braces - Block(BlockStmt<'a>), + Block(BlockStmt), /// A single semi-colon Empty, /// The contextual keyword `debugger` @@ -32,7 +32,7 @@ pub enum Stmt<'a> { /// } /// //rand !== 0 /// ``` - With(WithStmt<'a>), + With(WithStmt), /// A return statement /// ```js /// function thing() { @@ -41,14 +41,14 @@ pub enum Stmt<'a> { /// function stuff() { /// return; /// } - Return(Option>), + Return(Option>), /// A labeled statement /// ```js /// label: { /// break label; /// } /// ``` - Labeled(LabeledStmt<'a>), + Labeled(LabeledStmt), /// A break statement /// ```js /// label: { @@ -58,7 +58,7 @@ pub enum Stmt<'a> { /// break; /// } /// ``` - Break(Option>), + Break(Option>), /// A short circuit continuation of a loop /// ```js /// label: while (true) { @@ -69,16 +69,16 @@ pub enum Stmt<'a> { /// } /// } /// ``` - Continue(Option>), + Continue(Option>), /// An if statement /// ```js /// if (1 < 2) { - /// console.log('Always true'); + /// console.log(Tlways true'); /// } else { /// console.log('Never true'); /// } /// ``` - If(IfStmt<'a>), + If(IfStmt), /// A switch statement /// ```js /// switch (Math.floor(Math.random()) * 10) { @@ -93,7 +93,7 @@ pub enum Stmt<'a> { /// return true; /// } /// ``` - Switch(SwitchStmt<'a>), + Switch(SwitchStmt), /// A statement that throws an error /// ```js /// function error() { @@ -104,7 +104,7 @@ pub enum Stmt<'a> { /// throw new Error('hohoho'); /// } /// ``` - Throw(Expr<'a>), + Throw(Expr), /// A try/catch block /// ```js /// try { @@ -115,7 +115,7 @@ pub enum Stmt<'a> { /// /// } /// ``` - Try(TryStmt<'a>), + Try(TryStmt), /// A while loop /// ```js /// while (false) { @@ -130,14 +130,14 @@ pub enum Stmt<'a> { /// } /// } /// ``` - While(WhileStmt<'a>), + While(WhileStmt), /// A while loop that executes its body first /// ```js /// do { - /// console.log('at least once') + /// console.log(Tt least once') /// } while (Math.floor(Math.random() * 100) < 75) /// ``` - DoWhile(DoWhileStmt<'a>), + DoWhile(DoWhileStmt), /// A "c-style" for loop /// ```js /// for (var i = 0; i < 100; i++) console.log(i); @@ -145,7 +145,7 @@ pub enum Stmt<'a> { /// console.log('forever!'); /// } /// ``` - For(ForStmt<'a>), + For(ForStmt), /// A for in statement, this kind of for statement /// will extract each key from an indexable thing /// ```js @@ -158,7 +158,7 @@ pub enum Stmt<'a> { /// } /// //prints a, b /// ``` - ForIn(ForInStmt<'a>), + ForIn(ForInStmt), /// A for of statement, this kind of for statement /// will extract the value from a generator or iterator /// ```js @@ -167,13 +167,13 @@ pub enum Stmt<'a> { /// } /// //prints 2, 3, 4, 5, 6 /// ``` - ForOf(ForOfStmt<'a>), + ForOf(ForOfStmt), /// A var statement /// ```js /// var x; /// var x, y = 'huh?'; /// ``` - Var(Vec>), + Var(Vec>), } /// A with statement, this puts one object at the top of @@ -191,9 +191,9 @@ pub enum Stmt<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct WithStmt<'a> { - pub object: Expr<'a>, - pub body: Box>, +pub struct WithStmt { + pub object: Expr, + pub body: Box>, } /// A break statement @@ -207,25 +207,25 @@ pub struct WithStmt<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct LabeledStmt<'a> { - pub label: Ident<'a>, - pub body: Box>, +pub struct LabeledStmt { + pub label: Ident, + pub body: Box>, } /// An if statement /// ```js /// if (1 < 2) { -/// console.log('Always true'); +/// console.log(Tlways true'); /// } else { /// console.log('Never true'); /// } /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct IfStmt<'a> { - pub test: Expr<'a>, - pub consequent: Box>, - pub alternate: Option>>, +pub struct IfStmt { + pub test: Expr, + pub consequent: Box>, + pub alternate: Option>>, } /// A switch statement @@ -244,9 +244,9 @@ pub struct IfStmt<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct SwitchStmt<'a> { - pub discriminant: Expr<'a>, - pub cases: Vec>, +pub struct SwitchStmt { + pub discriminant: Expr, + pub cases: Vec>, } /// A single case part of a switch statement @@ -256,9 +256,9 @@ pub struct SwitchStmt<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct SwitchCase<'a> { - pub test: Option>, - pub consequent: Vec>, +pub struct SwitchCase { + pub test: Option>, + pub consequent: Vec>, } /// A collection of program parts wrapped in curly braces @@ -268,7 +268,7 @@ pub struct SwitchCase<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct BlockStmt<'a>(pub Vec>); +pub struct BlockStmt(pub Vec>); /// A try/catch block /// ```js @@ -282,10 +282,10 @@ pub struct BlockStmt<'a>(pub Vec>); /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct TryStmt<'a> { - pub block: BlockStmt<'a>, - pub handler: Option>, - pub finalizer: Option>, +pub struct TryStmt { + pub block: BlockStmt, + pub handler: Option>, + pub finalizer: Option>, } /// The error handling part of a `TryStmt` @@ -295,9 +295,9 @@ pub struct TryStmt<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub struct CatchClause<'a> { - pub param: Option>, - pub body: BlockStmt<'a>, +pub struct CatchClause { + pub param: Option>, + pub body: BlockStmt, } /// A while loop @@ -316,22 +316,22 @@ pub struct CatchClause<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct WhileStmt<'a> { - pub test: Expr<'a>, - pub body: Box>, +pub struct WhileStmt { + pub test: Expr, + pub body: Box>, } /// A while loop that executes its body first /// ```js /// do { -/// console.log('at least once') +/// console.log(Tt least once') /// } while (Math.floor(Math.random() * 100) < 75) /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct DoWhileStmt<'a> { - pub test: Expr<'a>, - pub body: Box>, +pub struct DoWhileStmt { + pub test: Expr, + pub body: Box>, } /// A "c-style" for loop @@ -343,11 +343,11 @@ pub struct DoWhileStmt<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ForStmt<'a> { - pub init: Option>, - pub test: Option>, - pub update: Option>, - pub body: Box>, +pub struct ForStmt { + pub init: Option>, + pub test: Option>, + pub update: Option>, + pub body: Box>, } /// The left most triple of a for loops parenthetical @@ -360,9 +360,9 @@ pub struct ForStmt<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum LoopInit<'a> { - Variable(VarKind, Vec>), - Expr(Expr<'a>), +pub enum LoopInit { + Variable(VarKind, Vec>), + Expr(Expr), } /// A for in statement, this kind of for statement @@ -379,10 +379,10 @@ pub enum LoopInit<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ForInStmt<'a> { - pub left: LoopLeft<'a>, - pub right: Expr<'a>, - pub body: Box>, +pub struct ForInStmt { + pub left: LoopLeft, + pub right: Expr, + pub body: Box>, } /// A for of statement, this kind of for statement @@ -395,10 +395,10 @@ pub struct ForInStmt<'a> { /// ``` #[derive(PartialEq, Debug, Clone)] #[cfg_attr(all(feature = "serialization"), derive(Deserialize, Serialize))] -pub struct ForOfStmt<'a> { - pub left: LoopLeft<'a>, - pub right: Expr<'a>, - pub body: Box>, +pub struct ForOfStmt { + pub left: LoopLeft, + pub right: Expr, + pub body: Box>, pub is_await: bool, } @@ -410,8 +410,8 @@ pub struct ForOfStmt<'a> { derive(Deserialize, Serialize) )] #[cfg_attr(all(feature = "serde", feature = "esprima"), derive(Deserialize))] -pub enum LoopLeft<'a> { - Expr(Expr<'a>), - Variable(VarKind, VarDecl<'a>), - Pat(Pat<'a>), +pub enum LoopLeft { + Expr(Expr), + Variable(VarKind, VarDecl), + Pat(Pat), }