From 061aa0dd7b7ad0e0d024c05b824a36a695d0a979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:01:30 +0900 Subject: [PATCH 01/32] Prepare work --- Cargo.toml | 1 + ecmascript/visit/Cargo.toml | 16 ++ ecmascript/visit/macros/Cargo.toml | 15 ++ ecmascript/visit/macros/src/lib.rs | 317 +++++++++++++++++++++++++++++ ecmascript/visit/src/lib.rs | 7 + 5 files changed, 356 insertions(+) create mode 100644 ecmascript/visit/Cargo.toml create mode 100644 ecmascript/visit/macros/Cargo.toml create mode 100644 ecmascript/visit/macros/src/lib.rs create mode 100644 ecmascript/visit/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 52bb69f09397..fd63dd5dca97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +members = ["ecmascript/visit"] [package] name = "swc" diff --git a/ecmascript/visit/Cargo.toml b/ecmascript/visit/Cargo.toml new file mode 100644 index 000000000000..d777a9ef3950 --- /dev/null +++ b/ecmascript/visit/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "swc_ecma_visit" +version = "0.1.0" +authors = ["강동윤 "] +license = "Apache-2.0/MIT" +repository = "https://github.com/swc-project/swc.git" +documentation = "https://swc-project.github.io/rustdoc/swc_ecma_visit/" +description = "Visitors for swc ecmascript nodes which works on stable rustc" +edition = "2018" + + +[dependencies] +swc_common = { version = "0.5.9", path = "../../common" } +swc_ecma_ast = { version = "0.18.0", path ="../ast" } +swc_ecma_visit_macros = { version = "0.1.0", path ="./macros" } +spez = "0.1.1" \ No newline at end of file diff --git a/ecmascript/visit/macros/Cargo.toml b/ecmascript/visit/macros/Cargo.toml new file mode 100644 index 000000000000..5e4544f93b60 --- /dev/null +++ b/ecmascript/visit/macros/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "swc_ecma_visit_macros" +version = "0.1.0" +authors = ["강동윤 "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +swc_macros_common = { version = "0.3", path ="../../../macros/common" } +proc-macro2 = "1" +pmutil = "0.5.1" +quote = "1" +syn = { version = "1", features = ["parsing", "full"] } diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs new file mode 100644 index 000000000000..679ef1b12f9c --- /dev/null +++ b/ecmascript/visit/macros/src/lib.rs @@ -0,0 +1,317 @@ +use pmutil::{q, IdentExt, ToTokensExt}; +use proc_macro2::Ident; +use swc_macros_common::def_site; +use syn::{ + parse::{Parse, ParseBuffer, ParseStream}, + parse_quote::parse, + punctuated::Punctuated, + Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, ImplItem, ImplItemMethod, + ItemImpl, ItemTrait, Member, Pat, PatStruct, Path, ReturnType, Signature, Stmt, Token, + TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, +}; + +/// This creates `Visit`. This is extensible visitor generator, and it +/// +/// - works with stable rustc +/// +/// - highly extensible and used to create Visitor for any types +/// +/// If there's a need, I'll publish the macro with generic name. +/// +/// - will be extended create `VisitMut` and `Fold` in future +/// +/// (If there's a request) +/// +/// +/// # Basic +/// +/// - Method name is determined based on type's name. +/// - All arguments follow the syntax of argument. (This makes rustfmt happy) +/// +/// +/// # Struct +/// +/// ```ignore +/// pub struct Struct { +/// pub field: String, +/// } +/// +/// define!(Struct { field }, String); +/// ``` +/// +/// generates (code which behaves like) +/// +/// ``` +/// pub trait Visit { +/// fn visit_struct(&mut self, n: &Struct) { +/// self.visit_string(&n.field) +/// } +/// +/// fn visit_string(&mut self, n: &String) {} +/// } +/// ``` +/// +/// +/// +/// # Enum +/// +/// ```ignore +/// pub enum Enum { +/// StructLike { field: String }, +/// TupleLike(String, u64), +/// UnitLike, +/// } +/// +/// define!( +/// Value(StructLike { field }, TupleLike(a, b), UnitLike), +/// String, +/// u64 +/// ); +/// ``` +/// +/// generates (code which behaves like) +/// +/// ``` +/// pub trait Visit { +/// fn visit_enum(&mut self, n: &Enum) { +/// match n { +/// Enum::StructLike { field } => self.visit_string(field), +/// Enum::TupleLike(_0, _1) => { +/// self.visit_string(_0); +/// self.visit_u64(_1); +/// } +/// Enum::UnitLike => {} +/// } +/// } +/// fn visit_string(&mut self, n: &String) {} +/// fn visit_u64(&mut self, n: &u64) {} +/// } +/// ``` +#[proc_macro] +pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input: Input = parse(tts.into()); + let args = input.args; + + // Required to generate specialization code. + let mut type_names = vec![]; + + let methods = args + .iter() + .map(|v| make_method(v, &mut type_names)) + .map(TraitItem::Method) + .collect::>(); + + ItemTrait { + attrs: vec![], + vis: Visibility::Public(VisPublic { + pub_token: def_site(), + }), + unsafety: None, + auto_token: None, + trait_token: def_site(), + ident: Ident::new("Visit", def_site()), + generics: Default::default(), + colon_token: None, + supertraits: Default::default(), + brace_token: def_site(), + items: methods, + } + .dump() + .into() +} + +fn handle_struct_expr(e: &ExprStruct) -> Block { + // We use auto(de)ref specialization + + let mut body = vec![]; + + for field in &e.fields { + match &field.member { + Member::Named(ref f) => { + body.push( + q!(Vars { field: f }, { + __visit(self, n.field); + }) + .parse(), + ); + } + + Member::Unnamed(_) => unimplemented!("unnamed member?"), + } + } + + Block { + brace_token: def_site(), + stmts: body, + } +} + +fn make_arm(e: &Expr) -> Arm { + fn make_arm_from_struct(e: &ExprStruct) -> Arm { + let mut stmts = vec![]; + for field in &e.fields { + match &field.member { + Member::Named(ref f) => { + let stmt = q!(Vars { field: f }, { + __visit(self, field); + }) + .parse(); + stmts.push(stmt); + } + + Member::Unnamed(_) => unimplemented!("unnamed member?"), + } + } + + let block = Block { + brace_token: def_site(), + stmts, + }; + + Arm { + attrs: vec![], + pat: q!((n)).parse(), + guard: None, + fat_arrow_token: def_site(), + body: Box::new(Expr::Block(ExprBlock { + attrs: vec![], + label: None, + block, + })), + comma: None, + } + } + + fn make_arm_from_call(e: &ExprCall) -> Arm { + let mut stmts = vec![]; + + for field in e.args {} + + let block = Block { + brace_token: def_site(), + stmts, + }; + + Arm { + attrs: vec![], + pat: q!((n)).parse(), + guard: None, + fat_arrow_token: def_site(), + body: Box::new(Expr::Block(ExprBlock { + attrs: vec![], + label: None, + block, + })), + comma: None, + } + } + + match e { + Expr::Struct(s) => make_arm_from_struct(s), + Expr::Call(c) => make_arm_from_call(c), + } +} + +fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { + match e { + Expr::Struct(s) => { + let type_name = s.path.get_ident().as_ref().unwrap().clone(); + type_names.push(type_name.clone()); + + let block = handle_struct_expr(s); + + TraitItemMethod { + attrs: vec![], + sig: method_sig(type_name), + default: Some(block), + semi_token: None, + } + } + Expr::Call(e) => match *e.func { + Expr::Path(ref callee) => { + let type_name = callee.path.get_ident().as_ref().unwrap().clone(); + type_names.push(type_name.clone()); + // + + let block = { + let mut arms = vec![]; + + for variant in &e.args { + match variant { + Expr::Struct(ref s) => { + arms.push(make_arm_from_struct(&s)); + } + Expr::Call(ref c) => {} + _ => {} + } + } + + Block { + brace_token: def_site(), + stmts: vec![Stmt::Expr(Expr::Match(ExprMatch { + attrs: vec![], + match_token: def_site(), + expr: q!((n)).parse(), + brace_token: def_site(), + arms, + }))], + } + }; + + TraitItemMethod { + attrs: vec![], + sig: method_sig(type_name), + default: Some(block), + semi_token: None, + } + } + _ => unimplemented!( + "proper error reporting for CallExpression with callee other than ident" + ), + }, + _ => unimplemented!("proper error reporting expressions other than struct / call"), + } +} + +struct Input { + /// + /// ``` + /// Struct{ fields } + /// ``` + /// + /// ``` + /// Enum([Variant1, StructLike { fields }]) + /// ``` + args: Punctuated, +} + +impl Parse for Input { + fn parse(input: ParseStream) -> Result { + Ok(Self { + args: Punctuated::parse_separated_nonempty(input)?, + }) + } +} + +fn method_sig(type_name: &Ident) -> Signature { + Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: def_site(), + ident: type_name.new_ident_with(|v| format!("visit_{}", v)), + generics: Default::default(), + paren_token: def_site(), + inputs: { + let mut p = Punctuated::default(); + p.push_value(q!(Vars {}, { &self }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars { Type: type_name }, { n: &Type }).parse()); + + p + }, + variadic: None, + output: ReturnType::Default, + } +} diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs new file mode 100644 index 000000000000..a5af2e685f92 --- /dev/null +++ b/ecmascript/visit/src/lib.rs @@ -0,0 +1,7 @@ +use swc_ecma_visit_macros::define; + +define!( + Struct { field, field2 }, + Vars {}, + Enum(StructLiek { field }) +); From 7f657ea2f789aaac49e0110c5e34ae12e910fc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:11:35 +0900 Subject: [PATCH 02/32] Fix --- ecmascript/visit/macros/src/lib.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 679ef1b12f9c..40161a9b0802 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -185,7 +185,7 @@ fn make_arm(e: &Expr) -> Arm { fn make_arm_from_call(e: &ExprCall) -> Arm { let mut stmts = vec![]; - for field in e.args {} + for field in &e.args {} let block = Block { brace_token: def_site(), @@ -194,7 +194,7 @@ fn make_arm(e: &Expr) -> Arm { Arm { attrs: vec![], - pat: q!((n)).parse(), + pat: q!(Vars { Enum: &e.func }, { Enum::Variant }).parse(), guard: None, fat_arrow_token: def_site(), body: Box::new(Expr::Block(ExprBlock { @@ -209,6 +209,7 @@ fn make_arm(e: &Expr) -> Arm { match e { Expr::Struct(s) => make_arm_from_struct(s), Expr::Call(c) => make_arm_from_call(c), + _ => unimplemented!("make_arg for {:?}", e), } } @@ -237,13 +238,7 @@ fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { let mut arms = vec![]; for variant in &e.args { - match variant { - Expr::Struct(ref s) => { - arms.push(make_arm_from_struct(&s)); - } - Expr::Call(ref c) => {} - _ => {} - } + arms.push(make_arm(variant)); } Block { From 322f39f86e853fb88c1c4c801dd055aab0d2790b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:21:12 +0900 Subject: [PATCH 03/32] More work --- ecmascript/visit/macros/src/lib.rs | 62 ++++++++++++++++++++++++------ ecmascript/visit/src/lib.rs | 5 +-- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 40161a9b0802..a180c0b12004 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -146,10 +146,10 @@ fn handle_struct_expr(e: &ExprStruct) -> Block { } } -fn make_arm(e: &Expr) -> Arm { - fn make_arm_from_struct(e: &ExprStruct) -> Arm { +fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { + fn make_arm_from_struct(e: Option<&Expr>, variant: &ExprStruct) -> Arm { let mut stmts = vec![]; - for field in &e.fields { + for field in &variant.fields { match &field.member { Member::Named(ref f) => { let stmt = q!(Vars { field: f }, { @@ -170,7 +170,23 @@ fn make_arm(e: &Expr) -> Arm { Arm { attrs: vec![], - pat: q!((n)).parse(), + pat: match e { + Some(e) => q!( + Vars { + Enum: e, + Variant: &variant.path + }, + { Enum::Variant { fields } } + ) + .parse(), + None => q!( + Vars { + Variant: &variant.path + }, + { Variant { fields } } + ) + .parse(), + }, guard: None, fat_arrow_token: def_site(), body: Box::new(Expr::Block(ExprBlock { @@ -182,10 +198,16 @@ fn make_arm(e: &Expr) -> Arm { } } - fn make_arm_from_call(e: &ExprCall) -> Arm { + fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { let mut stmts = vec![]; - for field in &e.args {} + for field in &variant.args { + let stmt = q!(Vars { field }, { + __visit(self, field); + }) + .parse(); + stmts.push(stmt); + } let block = Block { brace_token: def_site(), @@ -194,7 +216,23 @@ fn make_arm(e: &Expr) -> Arm { Arm { attrs: vec![], - pat: q!(Vars { Enum: &e.func }, { Enum::Variant }).parse(), + pat: match e { + Some(e) => q!( + Vars { + Enum: e, + Variant: &variant.func + }, + { Enum::Variant(fields) } + ) + .parse(), + None => q!( + Vars { + Variant: &variant.func + }, + { Variant(fields) } + ) + .parse(), + }, guard: None, fat_arrow_token: def_site(), body: Box::new(Expr::Block(ExprBlock { @@ -206,10 +244,10 @@ fn make_arm(e: &Expr) -> Arm { } } - match e { - Expr::Struct(s) => make_arm_from_struct(s), - Expr::Call(c) => make_arm_from_call(c), - _ => unimplemented!("make_arg for {:?}", e), + match variant { + Expr::Struct(s) => make_arm_from_struct(e, s), + Expr::Call(c) => make_arm_from_call(e, c), + _ => unimplemented!("make_arg for {:?}", variant), } } @@ -238,7 +276,7 @@ fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { let mut arms = vec![]; for variant in &e.args { - arms.push(make_arm(variant)); + arms.push(make_arm(Some(&e.func), variant)); } Block { diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index a5af2e685f92..b4ed164fe535 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,7 +1,6 @@ use swc_ecma_visit_macros::define; define!( - Struct { field, field2 }, - Vars {}, - Enum(StructLiek { field }) + S { field, field2 }, + E(StructLike { field }, TupelLike(a, b)) ); From ef6029c690a806772a12845542e131eb5eed3d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:28:29 +0900 Subject: [PATCH 04/32] codegen for visitor (before using inflector) --- ecmascript/visit/macros/src/lib.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index a180c0b12004..e6ac77638296 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -5,9 +5,9 @@ use syn::{ parse::{Parse, ParseBuffer, ParseStream}, parse_quote::parse, punctuated::Punctuated, - Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, ImplItem, ImplItemMethod, - ItemImpl, ItemTrait, Member, Pat, PatStruct, Path, ReturnType, Signature, Stmt, Token, - TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, + Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, FieldPat, FieldValue, + ImplItem, ImplItemMethod, ItemImpl, ItemTrait, Member, Pat, PatStruct, Path, ReturnType, + Signature, Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -149,6 +149,8 @@ fn handle_struct_expr(e: &ExprStruct) -> Block { fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { fn make_arm_from_struct(e: Option<&Expr>, variant: &ExprStruct) -> Arm { let mut stmts = vec![]; + let mut fields: Punctuated = Default::default(); + for field in &variant.fields { match &field.member { Member::Named(ref f) => { @@ -161,6 +163,7 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { Member::Unnamed(_) => unimplemented!("unnamed member?"), } + fields.push(field.clone()); } let block = Block { @@ -174,14 +177,16 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { Some(e) => q!( Vars { Enum: e, - Variant: &variant.path + Variant: &variant.path, + fields }, { Enum::Variant { fields } } ) .parse(), None => q!( Vars { - Variant: &variant.path + Variant: &variant.path, + fields }, { Variant { fields } } ) @@ -200,6 +205,7 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { let mut stmts = vec![]; + let mut fields: Punctuated = Default::default(); for field in &variant.args { let stmt = q!(Vars { field }, { @@ -207,6 +213,8 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { }) .parse(); stmts.push(stmt); + + fields.push(field.clone()); } let block = Block { @@ -220,14 +228,16 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { Some(e) => q!( Vars { Enum: e, - Variant: &variant.func + Variant: &variant.func, + fields, }, { Enum::Variant(fields) } ) .parse(), None => q!( Vars { - Variant: &variant.func + Variant: &variant.func, + fields, }, { Variant(fields) } ) From 6be116220dcccf8a02b6e94aeea94ff408ef9c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:30:24 +0900 Subject: [PATCH 05/32] Inflector --- ecmascript/visit/macros/Cargo.toml | 1 + ecmascript/visit/macros/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ecmascript/visit/macros/Cargo.toml b/ecmascript/visit/macros/Cargo.toml index 5e4544f93b60..01aca57efff9 100644 --- a/ecmascript/visit/macros/Cargo.toml +++ b/ecmascript/visit/macros/Cargo.toml @@ -13,3 +13,4 @@ proc-macro2 = "1" pmutil = "0.5.1" quote = "1" syn = { version = "1", features = ["parsing", "full"] } +Inflector = "0.11.4" \ No newline at end of file diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index e6ac77638296..a28208b741d6 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -1,3 +1,4 @@ +use inflector::Inflector; use pmutil::{q, IdentExt, ToTokensExt}; use proc_macro2::Ident; use swc_macros_common::def_site; @@ -343,7 +344,7 @@ fn method_sig(type_name: &Ident) -> Signature { unsafety: None, abi: None, fn_token: def_site(), - ident: type_name.new_ident_with(|v| format!("visit_{}", v)), + ident: type_name.new_ident_with(|v| format!("visit_{}", v.to_snake_case())), generics: Default::default(), paren_token: def_site(), inputs: { From ff6067a117490fc934072fdba7501e4db4e97784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:32:09 +0900 Subject: [PATCH 06/32] tts --- ecmascript/visit/macros/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index a28208b741d6..bef8653badbe 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -102,7 +102,8 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { .map(TraitItem::Method) .collect::>(); - ItemTrait { + let mut tokens = q!({}); + tokens.push_tokens(&ItemTrait { attrs: vec![], vis: Visibility::Public(VisPublic { pub_token: def_site(), @@ -116,9 +117,9 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { supertraits: Default::default(), brace_token: def_site(), items: methods, - } - .dump() - .into() + }); + + tokens.into() } fn handle_struct_expr(e: &ExprStruct) -> Block { From d26cc412653dae302dc6c1c485c54a5e14461dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 11:34:06 +0900 Subject: [PATCH 07/32] __visit --- ecmascript/visit/macros/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index bef8653badbe..5c8346b78d8a 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -132,7 +132,7 @@ fn handle_struct_expr(e: &ExprStruct) -> Block { Member::Named(ref f) => { body.push( q!(Vars { field: f }, { - __visit(self, n.field); + __visit!(self, n.field); }) .parse(), ); @@ -157,7 +157,7 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { match &field.member { Member::Named(ref f) => { let stmt = q!(Vars { field: f }, { - __visit(self, field); + __visit!(self, field); }) .parse(); stmts.push(stmt); @@ -211,7 +211,7 @@ fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { for field in &variant.args { let stmt = q!(Vars { field }, { - __visit(self, field); + __visit!(self, field); }) .parse(); stmts.push(stmt); From f379fd2cc76bb8b23228555ad255e792e388ff44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 12:42:40 +0900 Subject: [PATCH 08/32] WIP: spez --- ecmascript/visit/macros/src/lib.rs | 59 ++++++++++++++++++++++++++++-- ecmascript/visit/src/lib.rs | 16 +++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 5c8346b78d8a..8137adf415a6 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -1,5 +1,5 @@ use inflector::Inflector; -use pmutil::{q, IdentExt, ToTokensExt}; +use pmutil::{q, smart_quote, IdentExt, ToTokensExt}; use proc_macro2::Ident; use swc_macros_common::def_site; use syn::{ @@ -102,7 +102,43 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { .map(TraitItem::Method) .collect::>(); - let mut tokens = q!({}); + let mut tokens = q!({ + use spez::spez; + }); + + // Create __visit + { + let mut tts = q!({ for x = &$f; }); + + for name in &type_names { + tts = tts.quote_with(smart_quote!(Vars { Type: name }, { + match Type { + $v.visit(&x), + } + })); + } + + tokens = tokens.quote_with(smart_quote!(Vars { tts }, { + // + // macro_rules! __visit { + // ($v:expr, $f:expr) => {{ + // let x = &$f; + // spez! {tts} + // }}; + // } + macro_rules! __visit { + ($v:expr, $f:expr) => {{ + spez! { + for x = &$f; + match String { + $v.visit_string(x); + } + } + }}; + } + })); + }; + tokens.push_tokens(&ItemTrait { attrs: vec![], vis: Visibility::Public(VisPublic { @@ -314,7 +350,24 @@ fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { "proper error reporting for CallExpression with callee other than ident" ), }, - _ => unimplemented!("proper error reporting expressions other than struct / call"), + + Expr::Path(e) => { + // + let type_name = e.path.get_ident().as_ref().unwrap().clone(); + type_names.push(type_name.clone()); + + TraitItemMethod { + attrs: vec![], + sig: method_sig(type_name), + default: Some(Block { + brace_token: def_site(), + stmts: vec![], + }), + semi_token: None, + } + } + + _ => unimplemented!("proper error reporting expressions other than struct / call / path"), } } diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index b4ed164fe535..bd6f96ac3d6b 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,6 +1,20 @@ use swc_ecma_visit_macros::define; +struct S { + field: String, + field2: u64, +} + +enum E { + StructLike { field: String }, + TupleLike(u32, u16), +} + define!( S { field, field2 }, - E(StructLike { field }, TupelLike(a, b)) + E(StructLike { field }, TupleLike(a, b)), + String, + u64, + u32, + u16 ); From f0283f94e1a690ebd894457d0d4dacc17e0dc83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 12:55:41 +0900 Subject: [PATCH 09/32] WIP: Merging spez --- ecmascript/visit/Cargo.toml | 1 - ecmascript/visit/macros/src/lib.rs | 48 +++++----- ecmascript/visit/macros/src/spez.rs | 65 ++++++++++++++ ecmascript/visit/macros/src/spez/parse.rs | 101 ++++++++++++++++++++++ 4 files changed, 192 insertions(+), 23 deletions(-) create mode 100644 ecmascript/visit/macros/src/spez.rs create mode 100644 ecmascript/visit/macros/src/spez/parse.rs diff --git a/ecmascript/visit/Cargo.toml b/ecmascript/visit/Cargo.toml index d777a9ef3950..6f0979dad0f9 100644 --- a/ecmascript/visit/Cargo.toml +++ b/ecmascript/visit/Cargo.toml @@ -13,4 +13,3 @@ edition = "2018" swc_common = { version = "0.5.9", path = "../../common" } swc_ecma_ast = { version = "0.18.0", path ="../ast" } swc_ecma_visit_macros = { version = "0.1.0", path ="./macros" } -spez = "0.1.1" \ No newline at end of file diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 8137adf415a6..7e86b4c010f8 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -11,6 +11,8 @@ use syn::{ Signature, Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, }; +mod spez; + /// This creates `Visit`. This is extensible visitor generator, and it /// /// - works with stable rustc @@ -102,9 +104,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { .map(TraitItem::Method) .collect::>(); - let mut tokens = q!({ - use spez::spez; - }); + let mut tokens = q!({}); // Create __visit { @@ -118,25 +118,29 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { })); } - tokens = tokens.quote_with(smart_quote!(Vars { tts }, { - // - // macro_rules! __visit { - // ($v:expr, $f:expr) => {{ - // let x = &$f; - // spez! {tts} - // }}; - // } - macro_rules! __visit { - ($v:expr, $f:expr) => {{ - spez! { - for x = &$f; - match String { - $v.visit_string(x); - } - } - }}; - } - })); + { + let tts = tts.into(); + self::spez::spez_impl(syn::parse_macro_input!(tts)); + } + // tokens.quote_with(smart_quote!(Vars { tts }, { + // // + // // macro_rules! __visit { + // // ($v:expr, $f:expr) => {{ + // // let x = &$f; + // // spez! {tts} + // // }}; + // // } + // macro_rules! __visit { + // ($v:expr, $f:expr) => {{ + // spez! { + // for x = &$f; + // match String { + // $v.visit_string(x); + // } + // } + // }}; + // } + // })); }; tokens.push_tokens(&ItemTrait { diff --git a/ecmascript/visit/macros/src/spez.rs b/ecmascript/visit/macros/src/spez.rs new file mode 100644 index 000000000000..4fb9ba821c2b --- /dev/null +++ b/ecmascript/visit/macros/src/spez.rs @@ -0,0 +1,65 @@ +use parse::Args; +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; + +pub mod parse; + +fn refs(n: usize) -> TokenStream2 { + let mut refs = TokenStream2::new(); + for _ in 0..n { + refs.extend(quote![&]); + } + refs +} + +pub fn spez_impl(args: Args) -> TokenStream2 { + let mut traits = TokenStream2::new(); + + let param_def = match args.param { + Some(param) => quote! { + let #param = self.0.take().unwrap(); + }, + None => quote! {}, + }; + + let n_arms = args.arms.len(); + + for (i, arm) in args.arms.into_iter().enumerate() { + let name = syn::Ident::new(&format!("Match{}", i + 1), Span::call_site()); + let body = arm.body; + let ty = arm.ty; + let generics = &arm.generics; + let where_clause = &arm.generics.where_clause; + let refs = refs(n_arms - i - 1); + let return_type = match arm.return_type { + Some(return_type) => quote! { #return_type }, + None => quote! { () }, + }; + + traits.extend(quote! { + trait #name { + type Return; + fn spez(&self) -> Self::Return; + } + impl #generics #name for #refs Match<#ty> #where_clause { + type Return = #return_type; + fn spez(&self) -> Self::Return { + #param_def + #body + } + } + }); + } + + let expr = args.expr; + let refs = refs(n_arms); + + quote! { + { + struct Match(core::cell::Cell>); + #traits + (#refs Match(core::cell::Cell::new(Some(#expr)))).spez() + } + } +} diff --git a/ecmascript/visit/macros/src/spez/parse.rs b/ecmascript/visit/macros/src/spez/parse.rs new file mode 100644 index 000000000000..bf9b2afc48f2 --- /dev/null +++ b/ecmascript/visit/macros/src/spez/parse.rs @@ -0,0 +1,101 @@ +use std::iter::{once, FromIterator}; +use syn::{punctuated::Punctuated, Token}; + +pub struct Args { + pub for_token: Token![for], + pub param: Option, + pub at_token: Option, + pub expr: syn::Expr, + pub semicolon_token: Token![;], + pub arms: Vec, +} + +pub struct Arm { + pub match_token: Token![match], + pub generics: syn::Generics, + pub ty: syn::Type, + pub arrow_token: Option]>, + pub return_type: Option, + pub body: syn::Block, +} + +impl syn::parse::Parse for Args { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let for_token = input.parse()?; + let param; + let at_token; + let expr; + if input.peek2(Token![=]) { + param = Some(input.parse()?); + at_token = Some(input.parse()?); + expr = input.parse()?; + } else if input.peek(syn::Ident) && input.peek2(Token![;]) { + let ident: syn::Ident = input.parse()?; + param = Some(ident.clone()); + at_token = None; + expr = ident_to_expr(ident); + } else { + param = None; + at_token = None; + expr = input.parse()?; + } + Ok(Self { + for_token, + param, + at_token, + expr, + semicolon_token: input.parse()?, + arms: { + let mut arms = Vec::new(); + while !input.is_empty() { + arms.push(input.parse()?); + } + arms + }, + }) + } +} + +impl syn::parse::Parse for Arm { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let match_token = input.parse()?; + let generics = if input.peek(Token![<]) { + input.parse()? + } else { + syn::Generics::default() + }; + let ty = input.parse()?; + let where_clause: Option = input.parse()?; + let (arrow_token, return_type) = if input.peek(Token![->]) { + (Some(input.parse()?), Some(input.parse()?)) + } else { + (None, None) + }; + let body = input.parse()?; + Ok(Self { + match_token, + generics: syn::Generics { + where_clause, + ..generics + }, + ty, + arrow_token, + return_type, + body, + }) + } +} + +fn ident_to_expr(ident: syn::Ident) -> syn::Expr { + syn::Expr::Path(syn::ExprPath { + attrs: Vec::new(), + qself: None, + path: syn::Path { + leading_colon: None, + segments: Punctuated::from_iter(once(syn::PathSegment { + ident, + arguments: syn::PathArguments::None, + })), + }, + }) +} From c29e86f908822418bc4002f3c42ef006743f2ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 31 Mar 2020 12:56:23 +0900 Subject: [PATCH 10/32] Move --- ecmascript/visit/macros/src/{spez.rs => spez/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ecmascript/visit/macros/src/{spez.rs => spez/mod.rs} (100%) diff --git a/ecmascript/visit/macros/src/spez.rs b/ecmascript/visit/macros/src/spez/mod.rs similarity index 100% rename from ecmascript/visit/macros/src/spez.rs rename to ecmascript/visit/macros/src/spez/mod.rs From eb69b23284e5494d6fa1667e17287de22cf24e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 17:34:45 +0900 Subject: [PATCH 11/32] Let's provide type information --- ecmascript/visit/macros/src/lib.rs | 39 --------- ecmascript/visit/macros/src/spez/mod.rs | 65 -------------- ecmascript/visit/macros/src/spez/parse.rs | 101 ---------------------- ecmascript/visit/src/lib.rs | 18 +++- 4 files changed, 16 insertions(+), 207 deletions(-) delete mode 100644 ecmascript/visit/macros/src/spez/mod.rs delete mode 100644 ecmascript/visit/macros/src/spez/parse.rs diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 7e86b4c010f8..207635fd4363 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -11,8 +11,6 @@ use syn::{ Signature, Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, }; -mod spez; - /// This creates `Visit`. This is extensible visitor generator, and it /// /// - works with stable rustc @@ -106,43 +104,6 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { let mut tokens = q!({}); - // Create __visit - { - let mut tts = q!({ for x = &$f; }); - - for name in &type_names { - tts = tts.quote_with(smart_quote!(Vars { Type: name }, { - match Type { - $v.visit(&x), - } - })); - } - - { - let tts = tts.into(); - self::spez::spez_impl(syn::parse_macro_input!(tts)); - } - // tokens.quote_with(smart_quote!(Vars { tts }, { - // // - // // macro_rules! __visit { - // // ($v:expr, $f:expr) => {{ - // // let x = &$f; - // // spez! {tts} - // // }}; - // // } - // macro_rules! __visit { - // ($v:expr, $f:expr) => {{ - // spez! { - // for x = &$f; - // match String { - // $v.visit_string(x); - // } - // } - // }}; - // } - // })); - }; - tokens.push_tokens(&ItemTrait { attrs: vec![], vis: Visibility::Public(VisPublic { diff --git a/ecmascript/visit/macros/src/spez/mod.rs b/ecmascript/visit/macros/src/spez/mod.rs deleted file mode 100644 index 4fb9ba821c2b..000000000000 --- a/ecmascript/visit/macros/src/spez/mod.rs +++ /dev/null @@ -1,65 +0,0 @@ -use parse::Args; -use proc_macro::TokenStream; -use proc_macro2::{Span, TokenStream as TokenStream2}; -use quote::quote; - -pub mod parse; - -fn refs(n: usize) -> TokenStream2 { - let mut refs = TokenStream2::new(); - for _ in 0..n { - refs.extend(quote![&]); - } - refs -} - -pub fn spez_impl(args: Args) -> TokenStream2 { - let mut traits = TokenStream2::new(); - - let param_def = match args.param { - Some(param) => quote! { - let #param = self.0.take().unwrap(); - }, - None => quote! {}, - }; - - let n_arms = args.arms.len(); - - for (i, arm) in args.arms.into_iter().enumerate() { - let name = syn::Ident::new(&format!("Match{}", i + 1), Span::call_site()); - let body = arm.body; - let ty = arm.ty; - let generics = &arm.generics; - let where_clause = &arm.generics.where_clause; - let refs = refs(n_arms - i - 1); - let return_type = match arm.return_type { - Some(return_type) => quote! { #return_type }, - None => quote! { () }, - }; - - traits.extend(quote! { - trait #name { - type Return; - fn spez(&self) -> Self::Return; - } - impl #generics #name for #refs Match<#ty> #where_clause { - type Return = #return_type; - fn spez(&self) -> Self::Return { - #param_def - #body - } - } - }); - } - - let expr = args.expr; - let refs = refs(n_arms); - - quote! { - { - struct Match(core::cell::Cell>); - #traits - (#refs Match(core::cell::Cell::new(Some(#expr)))).spez() - } - } -} diff --git a/ecmascript/visit/macros/src/spez/parse.rs b/ecmascript/visit/macros/src/spez/parse.rs deleted file mode 100644 index bf9b2afc48f2..000000000000 --- a/ecmascript/visit/macros/src/spez/parse.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::iter::{once, FromIterator}; -use syn::{punctuated::Punctuated, Token}; - -pub struct Args { - pub for_token: Token![for], - pub param: Option, - pub at_token: Option, - pub expr: syn::Expr, - pub semicolon_token: Token![;], - pub arms: Vec, -} - -pub struct Arm { - pub match_token: Token![match], - pub generics: syn::Generics, - pub ty: syn::Type, - pub arrow_token: Option]>, - pub return_type: Option, - pub body: syn::Block, -} - -impl syn::parse::Parse for Args { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let for_token = input.parse()?; - let param; - let at_token; - let expr; - if input.peek2(Token![=]) { - param = Some(input.parse()?); - at_token = Some(input.parse()?); - expr = input.parse()?; - } else if input.peek(syn::Ident) && input.peek2(Token![;]) { - let ident: syn::Ident = input.parse()?; - param = Some(ident.clone()); - at_token = None; - expr = ident_to_expr(ident); - } else { - param = None; - at_token = None; - expr = input.parse()?; - } - Ok(Self { - for_token, - param, - at_token, - expr, - semicolon_token: input.parse()?, - arms: { - let mut arms = Vec::new(); - while !input.is_empty() { - arms.push(input.parse()?); - } - arms - }, - }) - } -} - -impl syn::parse::Parse for Arm { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let match_token = input.parse()?; - let generics = if input.peek(Token![<]) { - input.parse()? - } else { - syn::Generics::default() - }; - let ty = input.parse()?; - let where_clause: Option = input.parse()?; - let (arrow_token, return_type) = if input.peek(Token![->]) { - (Some(input.parse()?), Some(input.parse()?)) - } else { - (None, None) - }; - let body = input.parse()?; - Ok(Self { - match_token, - generics: syn::Generics { - where_clause, - ..generics - }, - ty, - arrow_token, - return_type, - body, - }) - } -} - -fn ident_to_expr(ident: syn::Ident) -> syn::Expr { - syn::Expr::Path(syn::ExprPath { - attrs: Vec::new(), - qself: None, - path: syn::Path { - leading_colon: None, - segments: Punctuated::from_iter(once(syn::PathSegment { - ident, - arguments: syn::PathArguments::None, - })), - }, - }) -} diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index bd6f96ac3d6b..2d20eb7123d8 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,5 +1,16 @@ +use std::any::Any; +use swc_common::AstNode; use swc_ecma_visit_macros::define; +/// Visitable nodes. +pub trait Node: Any {} + +impl Node for T where T: Any {} + +pub trait Visit { + fn visit(&mut self, node: &dyn Node, parent: &dyn Node); +} + struct S { field: String, field2: u64, @@ -11,8 +22,11 @@ enum E { } define!( - S { field, field2 }, - E(StructLike { field }, TupleLike(a, b)), + S { + field: String, + field2: u64 + }, + E(StructLike { field: String }, TupleLike(u32, u16)), String, u64, u32, From 313e6a937013980726b34f9c33c458740b45311e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 19:02:19 +0900 Subject: [PATCH 12/32] macro is done! --- ecmascript/visit/macros/src/lib.rs | 256 +++++++++++++++-------------- ecmascript/visit/src/lib.rs | 6 +- 2 files changed, 138 insertions(+), 124 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 207635fd4363..9f97f960c285 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -123,144 +123,146 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { tokens.into() } -fn handle_struct_expr(e: &ExprStruct) -> Block { - // We use auto(de)ref specialization +fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { + match variant { + Expr::Struct(s) => make_arm_from_struct(e, s), + Expr::Call(c) => make_arm_from_call(e, c), + _ => unimplemented!("make_arg for {:?}", variant), + } +} - let mut body = vec![]; +fn make_arm_from_struct(e: Option<&Expr>, variant: &ExprStruct) -> Arm { + let mut stmts = vec![]; + let mut fields: Punctuated = Default::default(); + + for field in &variant.fields { + let ty = match &field.expr { + Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), + _ => unimplemented!("proper error reporting for non-path expressions is tuple structs"), + }; + let visit_name = ty.new_ident_with(method_name); - for field in &e.fields { match &field.member { Member::Named(ref f) => { - body.push( - q!(Vars { field: f }, { - __visit!(self, n.field); - }) - .parse(), - ); + let stmt = q!( + Vars { + field: f, + visit_name + }, + { + self.visit_name(field, n as _); + } + ) + .parse(); + stmts.push(stmt); + + fields.push(FieldValue { + expr: q!(Vars { f }, { f }).parse(), + ..field.clone() + }); } Member::Unnamed(_) => unimplemented!("unnamed member?"), } } - Block { + let block = Block { brace_token: def_site(), - stmts: body, + stmts, + }; + + Arm { + attrs: vec![], + pat: match e { + Some(e) => q!( + Vars { + Enum: e, + Variant: &variant.path, + fields + }, + { Enum::Variant { fields } } + ) + .parse(), + None => q!( + Vars { + Variant: &variant.path, + fields + }, + { Variant { fields } } + ) + .parse(), + }, + guard: None, + fat_arrow_token: def_site(), + body: Box::new(Expr::Block(ExprBlock { + attrs: vec![], + label: None, + block, + })), + comma: None, } } -fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { - fn make_arm_from_struct(e: Option<&Expr>, variant: &ExprStruct) -> Arm { - let mut stmts = vec![]; - let mut fields: Punctuated = Default::default(); - - for field in &variant.fields { - match &field.member { - Member::Named(ref f) => { - let stmt = q!(Vars { field: f }, { - __visit!(self, field); - }) - .parse(); - stmts.push(stmt); - } - - Member::Unnamed(_) => unimplemented!("unnamed member?"), - } - fields.push(field.clone()); - } +fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { + let mut stmts = vec![]; + let mut bindings: Punctuated<_, Token![,]> = Default::default(); - let block = Block { - brace_token: def_site(), - stmts, + for (i, ty) in variant.args.iter().enumerate() { + let ty = match ty { + Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), + _ => unimplemented!("proper error reporting for non-path expressions is tuple structs"), }; - - Arm { - attrs: vec![], - pat: match e { - Some(e) => q!( - Vars { - Enum: e, - Variant: &variant.path, - fields - }, - { Enum::Variant { fields } } - ) - .parse(), - None => q!( - Vars { - Variant: &variant.path, - fields - }, - { Variant { fields } } - ) - .parse(), + let field_name = Ident::new(&format!("_{}", i), ty.span()); + let visit_name = ty.new_ident_with(method_name); + let stmt = q!( + Vars { + field_name: &field_name, + visit_name, }, - guard: None, - fat_arrow_token: def_site(), - body: Box::new(Expr::Block(ExprBlock { - attrs: vec![], - label: None, - block, - })), - comma: None, - } - } - - fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { - let mut stmts = vec![]; - let mut fields: Punctuated = Default::default(); - - for field in &variant.args { - let stmt = q!(Vars { field }, { - __visit!(self, field); - }) - .parse(); - stmts.push(stmt); + { + self.visit_name(field_name, n as _); + } + ) + .parse(); + stmts.push(stmt); - fields.push(field.clone()); - } + bindings.push(field_name.clone()); + } - let block = Block { - brace_token: def_site(), - stmts, - }; + let block = Block { + brace_token: def_site(), + stmts, + }; - Arm { + Arm { + attrs: vec![], + pat: match e { + Some(e) => q!( + Vars { + Enum: e, + Variant: &variant.func, + bindings, + }, + { Enum::Variant(bindings) } + ) + .parse(), + None => q!( + Vars { + Variant: &variant.func, + bindings, + }, + { Variant(bindings) } + ) + .parse(), + }, + guard: None, + fat_arrow_token: def_site(), + body: Box::new(Expr::Block(ExprBlock { attrs: vec![], - pat: match e { - Some(e) => q!( - Vars { - Enum: e, - Variant: &variant.func, - fields, - }, - { Enum::Variant(fields) } - ) - .parse(), - None => q!( - Vars { - Variant: &variant.func, - fields, - }, - { Variant(fields) } - ) - .parse(), - }, - guard: None, - fat_arrow_token: def_site(), - body: Box::new(Expr::Block(ExprBlock { - attrs: vec![], - label: None, - block, - })), - comma: None, - } - } - - match variant { - Expr::Struct(s) => make_arm_from_struct(e, s), - Expr::Call(c) => make_arm_from_call(e, c), - _ => unimplemented!("make_arg for {:?}", variant), + label: None, + block, + })), + comma: None, } } @@ -270,7 +272,17 @@ fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { let type_name = s.path.get_ident().as_ref().unwrap().clone(); type_names.push(type_name.clone()); - let block = handle_struct_expr(s); + let block = { + let arm = make_arm_from_struct(None, &s); + + let mut match_expr: ExprMatch = q!((match n {})).parse(); + match_expr.arms.push(arm); + + Block { + brace_token: def_site(), + stmts: vec![q!(Vars { match_expr }, { match_expr }).parse()], + } + }; TraitItemMethod { attrs: vec![], @@ -363,7 +375,7 @@ fn method_sig(type_name: &Ident) -> Signature { unsafety: None, abi: None, fn_token: def_site(), - ident: type_name.new_ident_with(|v| format!("visit_{}", v.to_snake_case())), + ident: type_name.new_ident_with(method_name), generics: Default::default(), paren_token: def_site(), inputs: { @@ -371,6 +383,8 @@ fn method_sig(type_name: &Ident) -> Signature { p.push_value(q!(Vars {}, { &self }).parse()); p.push_punct(def_site()); p.push_value(q!(Vars { Type: type_name }, { n: &Type }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); p }, @@ -378,3 +392,7 @@ fn method_sig(type_name: &Ident) -> Signature { output: ReturnType::Default, } } + +fn method_name(v: &str) -> String { + format!("visit_{}", v.to_snake_case()) +} diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index 2d20eb7123d8..754e8de9a7cc 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -5,11 +5,7 @@ use swc_ecma_visit_macros::define; /// Visitable nodes. pub trait Node: Any {} -impl Node for T where T: Any {} - -pub trait Visit { - fn visit(&mut self, node: &dyn Node, parent: &dyn Node); -} +impl Node for T where T: Any {} struct S { field: String, From e55dfada73960c8c483587c8e98bbd73aca76146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 19:52:59 +0900 Subject: [PATCH 13/32] WIP: block-based approach --- ecmascript/visit/macros/src/lib.rs | 299 ++-- ecmascript/visit/scripts/update.sh | 13 + ecmascript/visit/src/lib.rs | 2421 +++++++++++++++++++++++++++- 3 files changed, 2540 insertions(+), 193 deletions(-) create mode 100644 ecmascript/visit/scripts/update.sh diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 9f97f960c285..ee2e3af60ca9 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -6,9 +6,11 @@ use syn::{ parse::{Parse, ParseBuffer, ParseStream}, parse_quote::parse, punctuated::Punctuated, + spanned::Spanned, Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, FieldPat, FieldValue, - ImplItem, ImplItemMethod, ItemImpl, ItemTrait, Member, Pat, PatStruct, Path, ReturnType, - Signature, Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, VisPublic, Visibility, + Fields, ImplItem, ImplItemMethod, Item, ItemEnum, ItemImpl, ItemMod, ItemStruct, ItemTrait, + Member, Pat, PatStruct, Path, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMacro, + TraitItemMethod, Type, Variant, VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -90,17 +92,21 @@ use syn::{ /// ``` #[proc_macro] pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: Input = parse(tts.into()); - let args = input.args; + let block: Block = parse(tts.into()); // Required to generate specialization code. let mut type_names = vec![]; + let mut methods = vec![]; - let methods = args - .iter() - .map(|v| make_method(v, &mut type_names)) - .map(TraitItem::Method) - .collect::>(); + for stmts in block.stmts { + let item = match stmts { + Stmt::Item(item) => item, + _ => unimplemented!("error reporting for something other than Item"), + }; + + let mtd = make_method(item, &mut type_names); + methods.push(TraitItem::Method(mtd)); + } let mut tokens = q!({}); @@ -123,110 +129,21 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { tokens.into() } -fn make_arm(e: Option<&Expr>, variant: &Expr) -> Arm { - match variant { - Expr::Struct(s) => make_arm_from_struct(e, s), - Expr::Call(c) => make_arm_from_call(e, c), - _ => unimplemented!("make_arg for {:?}", variant), - } -} - -fn make_arm_from_struct(e: Option<&Expr>, variant: &ExprStruct) -> Arm { +fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { let mut stmts = vec![]; let mut fields: Punctuated = Default::default(); - for field in &variant.fields { - let ty = match &field.expr { - Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), - _ => unimplemented!("proper error reporting for non-path expressions is tuple structs"), - }; - let visit_name = ty.new_ident_with(method_name); - - match &field.member { - Member::Named(ref f) => { - let stmt = q!( - Vars { - field: f, - visit_name - }, - { - self.visit_name(field, n as _); - } - ) - .parse(); - stmts.push(stmt); - - fields.push(FieldValue { - expr: q!(Vars { f }, { f }).parse(), - ..field.clone() - }); - } - - Member::Unnamed(_) => unimplemented!("unnamed member?"), - } - } - - let block = Block { - brace_token: def_site(), - stmts, - }; - - Arm { - attrs: vec![], - pat: match e { - Some(e) => q!( - Vars { - Enum: e, - Variant: &variant.path, - fields - }, - { Enum::Variant { fields } } - ) - .parse(), - None => q!( - Vars { - Variant: &variant.path, - fields - }, - { Variant { fields } } - ) - .parse(), - }, - guard: None, - fat_arrow_token: def_site(), - body: Box::new(Expr::Block(ExprBlock { - attrs: vec![], - label: None, - block, - })), - comma: None, - } -} - -fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { - let mut stmts = vec![]; - let mut bindings: Punctuated<_, Token![,]> = Default::default(); + for field in variant { + let ty = &field.ty; + let visit_name = method_name(&ty); - for (i, ty) in variant.args.iter().enumerate() { - let ty = match ty { - Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), - _ => unimplemented!("proper error reporting for non-path expressions is tuple structs"), - }; - let field_name = Ident::new(&format!("_{}", i), ty.span()); - let visit_name = ty.new_ident_with(method_name); - let stmt = q!( - Vars { - field_name: &field_name, - visit_name, - }, - { - self.visit_name(field_name, n as _); - } - ) + let stmt = q!(Vars { field, visit_name }, { + self.visit_name(field, n as _); + }) .parse(); stmts.push(stmt); - bindings.push(field_name.clone()); + fields.push(q!(Vars { field }, { field }).parse()); } let block = Block { @@ -236,25 +153,7 @@ fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { Arm { attrs: vec![], - pat: match e { - Some(e) => q!( - Vars { - Enum: e, - Variant: &variant.func, - bindings, - }, - { Enum::Variant(bindings) } - ) - .parse(), - None => q!( - Vars { - Variant: &variant.func, - bindings, - }, - { Variant(bindings) } - ) - .parse(), - }, + pat: q!(Vars { Path: path, fields }, { Path::Variant { fields } }).parse(), guard: None, fat_arrow_token: def_site(), body: Box::new(Expr::Block(ExprBlock { @@ -266,14 +165,77 @@ fn make_arm_from_call(e: Option<&Expr>, variant: &ExprCall) -> Arm { } } -fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { +// fn make_arm_from_call(e: Option<&ItemEnum>, variant: &ExprCall) -> Arm { +// let mut stmts = vec![]; +// let mut bindings: Punctuated<_, Token![,]> = Default::default(); +// +// for (i, ty) in variant.args.iter().enumerate() { +// let ty = match ty { +// Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), +// _ => unimplemented!("proper error reporting for non-path +// expressions is tuple structs"), }; +// let field_name = Ident::new(&format!("_{}", i), ty.span()); +// let visit_name = ty.new_ident_with(method_name); +// let stmt = q!( +// Vars { +// field_name: &field_name, +// visit_name, +// }, +// { +// self.visit_name(field_name, n as _); +// } +// ) +// .parse(); +// stmts.push(stmt); +// +// bindings.push(field_name.clone()); +// } +// +// let block = Block { +// brace_token: def_site(), +// stmts, +// }; +// +// Arm { +// attrs: vec![], +// pat: match e { +// Some(e) => q!( +// Vars { +// Enum: e, +// Variant: &variant.func, +// bindings, +// }, +// { Enum::Variant(bindings) } +// ) +// .parse(), +// None => q!( +// Vars { +// Variant: &variant.func, +// bindings, +// }, +// { Variant(bindings) } +// ) +// .parse(), +// }, +// guard: None, +// fat_arrow_token: def_site(), +// body: Box::new(Expr::Block(ExprBlock { +// attrs: vec![], +// label: None, +// block, +// })), +// comma: None, +// } +// } + +fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { match e { - Expr::Struct(s) => { - let type_name = s.path.get_ident().as_ref().unwrap().clone(); + Item::Struct(s) => { + let type_name = &s.ident; type_names.push(type_name.clone()); let block = { - let arm = make_arm_from_struct(None, &s); + let arm = make_arm_from_struct(&s.ident.clone().into(), &s.fields); let mut match_expr: ExprMatch = q!((match n {})).parse(); match_expr.arms.push(arm); @@ -291,60 +253,51 @@ fn make_method(e: &Expr, type_names: &mut Vec) -> TraitItemMethod { semi_token: None, } } - Expr::Call(e) => match *e.func { - Expr::Path(ref callee) => { - let type_name = callee.path.get_ident().as_ref().unwrap().clone(); - type_names.push(type_name.clone()); - // - - let block = { - let mut arms = vec![]; + Item::Enum(e) => { + // + let type_name = &e.ident; + type_names.push(e.ident.clone()); + // - for variant in &e.args { - arms.push(make_arm(Some(&e.func), variant)); - } + let block = { + let mut arms = vec![]; + + for variant in &e.variants { + let arm = make_arm_from_struct( + &q!( + Vars { + Enum: e.ident, + Variant: variant.ident + }, + { Enum::Variant } + ) + .parse(), + &variant.fields, + ); + arms.push(arm); + } - Block { + Block { + brace_token: def_site(), + stmts: vec![Stmt::Expr(Expr::Match(ExprMatch { + attrs: vec![], + match_token: def_site(), + expr: q!((n)).parse(), brace_token: def_site(), - stmts: vec![Stmt::Expr(Expr::Match(ExprMatch { - attrs: vec![], - match_token: def_site(), - expr: q!((n)).parse(), - brace_token: def_site(), - arms, - }))], - } - }; - - TraitItemMethod { - attrs: vec![], - sig: method_sig(type_name), - default: Some(block), - semi_token: None, + arms, + }))], } - } - _ => unimplemented!( - "proper error reporting for CallExpression with callee other than ident" - ), - }, - - Expr::Path(e) => { - // - let type_name = e.path.get_ident().as_ref().unwrap().clone(); - type_names.push(type_name.clone()); + }; TraitItemMethod { attrs: vec![], sig: method_sig(type_name), - default: Some(Block { - brace_token: def_site(), - stmts: vec![], - }), + default: Some(block), semi_token: None, } } - _ => unimplemented!("proper error reporting expressions other than struct / call / path"), + _ => unimplemented!("proper error reporting for item other than struct / enum"), } } @@ -375,7 +328,7 @@ fn method_sig(type_name: &Ident) -> Signature { unsafety: None, abi: None, fn_token: def_site(), - ident: type_name.new_ident_with(method_name), + ident: type_name.clone(), generics: Default::default(), paren_token: def_site(), inputs: { @@ -393,6 +346,6 @@ fn method_sig(type_name: &Ident) -> Signature { } } -fn method_name(v: &str) -> String { +fn method_name(v: &Type) -> String { format!("visit_{}", v.to_snake_case()) } diff --git a/ecmascript/visit/scripts/update.sh b/ecmascript/visit/scripts/update.sh new file mode 100644 index 000000000000..6ea5c6a2e1e6 --- /dev/null +++ b/ecmascript/visit/scripts/update.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + + +for filename in ../ast/src/*.rs; do +# echo "$filename" + while read -r line; do + [[ "$line" =~ ^[[:space:]]*# ]] && continue + [[ "$line" =~ ^[[:space:]]*\/ ]] && continue + [[ "$line" =~ ^[[:space:]]*\/ ]] && continue + echo "$line" + done < "$filename" + +done \ No newline at end of file diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index 754e8de9a7cc..32d354bfe40c 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,30 +1,2411 @@ use std::any::Any; use swc_common::AstNode; -use swc_ecma_visit_macros::define; +use swc_ecma_visit_macros::{define, visit}; /// Visitable nodes. pub trait Node: Any {} impl Node for T where T: Any {} -struct S { - field: String, - field2: u64, -} +define!({ + pub struct Class { + pub span: Span, + + pub decorators: Vec, + + pub body: Vec, + + pub super_class: Option>, + + pub is_abstract: bool, + + pub type_params: Option, + + pub super_type_params: Option, + + pub implements: Vec, + } +}); + +#[visit] +mod types { + use crate::{ + expr::Expr, + function::{Function, PatOrTsParamProp}, + ident::PrivateName, + prop::PropName, + stmt::BlockStmt, + typescript::{ + Accessibility, TsExprWithTypeArgs, TsIndexSignature, TsTypeAnn, TsTypeParamDecl, + TsTypeParamInstantiation, + }, + }; + use serde::{Deserialize, Serialize}; + + pub struct Class { + pub span: Span, + + pub decorators: Vec, + + pub body: Vec, + + pub super_class: Option>, + + pub is_abstract: bool, + + pub type_params: Option, + + pub super_type_params: Option, + + pub implements: Vec, + } + + pub enum ClassMember { + Constructor(Constructor), + Method(ClassMethod), + PrivateMethod(PrivateMethod), + ClassProp(ClassProp), + PrivateProp(PrivateProp), + TsIndexSignature(TsIndexSignature), + } + + macro_rules! property { + ($name:ident, $ty:literal, $KEY:ty) => { + pub struct $name { + pub span: Span, + + pub key: $KEY, + + pub value: Option>, + + pub type_ann: Option, + + pub is_static: bool, + + pub decorators: Vec, + + pub computed: bool, + + pub accessibility: Option, + + pub is_abstract: bool, + + pub is_optional: bool, + + pub readonly: bool, + + pub definite: bool, + } + }; + } + + property!(ClassProp, "ClassProperty", Box); + property!(PrivateProp, "PrivateProperty", PrivateName); + + macro_rules! method { + ($name:ident, $ty:literal, $KEY:ty) => { + pub struct $name { + pub span: Span, + + pub key: $KEY, + + pub function: Function, + + pub kind: MethodKind, + + pub is_static: bool, + + pub accessibility: Option, + + pub is_abstract: bool, + + pub is_optional: bool, + } + }; + } + + method!(ClassMethod, "ClassMethod", PropName); + method!(PrivateMethod, "PrivateMethod", PrivateName); + + pub struct Constructor { + pub span: Span, + + pub key: PropName, + + pub params: Vec, + + pub body: Option, + + pub accessibility: Option, + + pub is_optional: bool, + } + + pub struct Decorator { + pub span: Span, + + pub expr: Box, + } + + pub enum MethodKind { + Method, + Getter, + Setter, + } + use crate::{ + class::Class, + expr::Expr, + function::Function, + ident::Ident, + pat::Pat, + typescript::{TsEnumDecl, TsInterfaceDecl, TsModuleDecl, TsTypeAliasDecl}, + }; + use string_enum::StringEnum; + use swc_common::{ast_node, Fold, Span}; + + pub enum Decl { + Class(ClassDecl), + Fn(FnDecl), + Var(VarDecl), + TsInterface(TsInterfaceDecl), + TsTypeAlias(TsTypeAliasDecl), + TsEnum(TsEnumDecl), + TsModule(TsModuleDecl), + } + + pub struct FnDecl { + pub ident: Ident, + + pub declare: bool, + + pub function: Function, + } + + pub struct ClassDecl { + pub ident: Ident, + + pub declare: bool, + + pub class: Class, + } + + pub struct VarDecl { + pub span: Span, + + pub kind: VarDeclKind, + + pub declare: bool, + + pub decls: Vec, + } + + pub enum VarDeclKind { + Var, + Let, + Const, + } + + pub struct VarDeclarator { + pub span: Span, + pub name: Pat, + + pub init: Option>, + + pub definite: bool, + } + use crate::{ + class::Class, + function::Function, + ident::{Ident, PrivateName}, + jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName}, + lit::{Bool, Lit, Number, Str}, + operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp}, + pat::Pat, + prop::Prop, + stmt::BlockStmt, + typescript::{ + TsAsExpr, TsConstAssertion, TsNonNullExpr, TsTypeAnn, TsTypeAssertion, TsTypeCastExpr, + TsTypeParamDecl, TsTypeParamInstantiation, + }, + Invalid, + }; + use serde::{self, Deserialize, Serialize}; + use swc_common::{ast_node, Fold, Span, Spanned, DUMMY_SP}; + + pub enum Expr { + This(ThisExpr), + + Array(ArrayLit), + + Object(ObjectLit), + + Fn(FnExpr), + + Unary(UnaryExpr), + + Update(UpdateExpr), + + Bin(BinExpr), + + Assign(AssignExpr), + + Member(MemberExpr), + + Cond(CondExpr), + + Call(CallExpr), + + New(NewExpr), + + Seq(SeqExpr), + + Ident(Ident), + + Lit(Lit), + + Tpl(Tpl), + + TaggedTpl(TaggedTpl), + + Arrow(ArrowExpr), + + Class(ClassExpr), + + Yield(YieldExpr), + + MetaProp(MetaPropExpr), + + Await(AwaitExpr), + + Paren(ParenExpr), + + JSXMember(JSXMemberExpr), + + JSXNamespacedName(JSXNamespacedName), + + JSXEmpty(JSXEmptyExpr), + + JSXElement(Box), + + JSXFragment(JSXFragment), + + TsTypeAssertion(TsTypeAssertion), + + TsConstAssertion(TsConstAssertion), + + TsNonNull(TsNonNullExpr), + + TsTypeCast(TsTypeCastExpr), + + TsAs(TsAsExpr), + + PrivateName(PrivateName), + + OptChain(OptChainExpr), + + Invalid(Invalid), + } + + pub struct ThisExpr { + pub span: Span, + } + + pub struct ArrayLit { + pub span: Span, + + pub elems: Vec>, + } + + pub struct ObjectLit { + pub span: Span, + + pub props: Vec, + } + + pub enum PropOrSpread { + Spread(SpreadElement), + + Prop(Box), + } + + pub struct SpreadElement { + pub dot3_token: Span, + + pub expr: Box, + } + + pub struct UnaryExpr { + pub span: Span, + + pub op: UnaryOp, + + pub arg: Box, + } + + pub struct UpdateExpr { + pub span: Span, + + pub op: UpdateOp, + + pub prefix: bool, + + pub arg: Box, + } + + pub struct BinExpr { + pub span: Span, + + pub op: BinaryOp, + + pub left: Box, + + pub right: Box, + } + + pub struct FnExpr { + pub ident: Option, + + pub function: Function, + } + + pub struct ClassExpr { + pub ident: Option, + + pub class: Class, + } + + pub struct AssignExpr { + pub span: Span, + + pub op: AssignOp, + + pub left: PatOrExpr, + + pub right: Box, + } + + pub struct MemberExpr { + pub span: Span, + + pub obj: ExprOrSuper, + + pub prop: Box, + + pub computed: bool, + } + + pub struct CondExpr { + pub span: Span, + + pub test: Box, + + pub cons: Box, + + pub alt: Box, + } + + pub struct CallExpr { + pub span: Span, + + pub callee: ExprOrSuper, + + pub args: Vec, + + pub type_args: Option, + } + + pub struct NewExpr { + pub span: Span, + + pub callee: Box, + + pub args: Option>, + + pub type_args: Option, + } + + pub struct SeqExpr { + pub span: Span, + + pub exprs: Vec>, + } + + pub struct ArrowExpr { + pub span: Span, + + pub params: Vec, + + pub body: BlockStmtOrExpr, + + pub is_async: bool, + + pub is_generator: bool, + + pub type_params: Option, + + pub return_type: Option, + } + + pub struct YieldExpr { + pub span: Span, + + pub arg: Option>, + + pub delegate: bool, + } + + pub struct MetaPropExpr { + pub meta: Ident, + + pub prop: Ident, + } + + pub struct AwaitExpr { + pub span: Span, + + pub arg: Box, + } + + pub struct Tpl { + pub span: Span, + + pub exprs: Vec>, + + pub quasis: Vec, + } + + pub struct TaggedTpl { + pub span: Span, + + pub tag: Box, + + pub exprs: Vec>, + pub quasis: Vec, + + pub type_params: Option, + } + + pub struct TplElement { + pub span: Span, + pub tail: bool, + pub cooked: Option, + pub raw: Str, + } + + pub struct ParenExpr { + pub span: Span, + + pub expr: Box, + } + + pub enum ExprOrSuper { + Super(Super), + + Expr(Box), + } + + pub struct Super { + pub span: Span, + } + + pub struct ExprOrSpread { + pub spread: Option, + + pub expr: Box, + } + + impl Spanned for ExprOrSpread { + fn span(&self) -> Span { + let expr = self.expr.span(); + match self.spread { + Some(spread) => expr.with_lo(spread.lo()), + None => expr, + } + } + } + + pub enum BlockStmtOrExpr { + BlockStmt(BlockStmt), + Expr(Box), + } + + pub enum PatOrExpr { + Expr(Box), + Pat(Box), + } + + impl From for Expr { + fn from(value: bool) -> Self { + Expr::Lit(Lit::Bool(Bool { + span: DUMMY_SP, + value, + })) + } + } + + impl From for Expr { + fn from(value: f64) -> Self { + Expr::Lit(Lit::Num(Number { + span: DUMMY_SP, + value, + })) + } + } + + impl From for Expr { + fn from(v: Bool) -> Self { + Expr::Lit(Lit::Bool(v)) + } + } + + impl From for Expr { + fn from(v: Number) -> Self { + Expr::Lit(Lit::Num(v)) + } + } + + impl From for Expr { + fn from(v: Str) -> Self { + Expr::Lit(Lit::Str(v)) + } + } + + pub struct OptChainExpr { + pub span: Span, + pub expr: Box, + } + + test_de!( + jsx_element, + JSXElement, + r#"{ +"type": "JSXElement", +"span": { +"start": 0, +"end": 5, +"ctxt": 0 +}, +"opening": { +"type": "JSXOpeningElement", +"name": { +"type": "Identifier", +"span": { +"start": 1, +"end": 2, +"ctxt": 0 +}, +"value": "a", +"optional": false +}, +"span": { +"start": 1, +"end": 5, +"ctxt": 0 +}, +"selfClosing": true +}, +"children": [], +"closing": null +}"# + ); + use crate::{ + class::Decorator, + pat::Pat, + stmt::BlockStmt, + typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl}, + }; + use swc_common::{ast_node, Span}; + + pub struct Function { + pub params: Vec, + + pub decorators: Vec, + + pub span: Span, + + pub body: Option, + + pub is_generator: bool, + + pub is_async: bool, + + pub type_params: Option, + + pub return_type: Option, + } + + pub enum PatOrTsParamProp { + TsParamProp(TsParamProp), + Pat(Pat), + } + use crate::typescript::TsTypeAnn; + use swc_atoms::JsWord; + use swc_common::{ast_node, Span}; + + pub struct Ident { + pub span: Span, + pub sym: JsWord, + pub type_ann: Option, + pub optional: bool, + } + + pub struct PrivateName { + pub span: Span, + pub id: Ident, + } + + impl AsRef for Ident { + fn as_ref(&self) -> &str { + &self.sym + } + } + + impl Ident { + pub const fn new(sym: JsWord, span: Span) -> Self { + Ident { + span, + sym, + type_ann: None, + optional: false, + } + } + } + + pub trait IdentExt: AsRef { + fn is_reserved_for_es3(&self) -> bool { + [ + "abstract", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "typeof", + "var", + "void", + "volatile", + "while", + "with", + ] + .contains(&self.as_ref()) + } + + fn is_reserved_only_for_es3(&self) -> bool { + [ + "abstract", + "boolean", + "byte", + "char", + "double", + "enum", + "final", + "float", + "goto", + "implements", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "synchronized", + "throws", + "transient", + "volatile", + ] + .contains(&self.as_ref()) + } + } + + impl IdentExt for JsWord {} + impl IdentExt for Ident {} + use crate::{ + expr::{Expr, SpreadElement}, + ident::Ident, + lit::Lit, + typescript::TsTypeParamInstantiation, + }; + use swc_atoms::JsWord; + use swc_common::{ast_node, Span}; + + pub enum JSXObject { + JSXMemberExpr(Box), + Ident(Ident), + } + + pub struct JSXMemberExpr { + pub obj: JSXObject, + + pub prop: Ident, + } + + pub struct JSXNamespacedName { + pub ns: Ident, + pub name: Ident, + } + + pub struct JSXEmptyExpr { + pub span: Span, + } + + pub struct JSXExprContainer { + pub span: Span, + pub expr: JSXExpr, + } + + pub enum JSXExpr { + JSXEmptyExpr(JSXEmptyExpr), + Expr(Box), + } + + pub struct JSXSpreadChild { + pub span: Span, + pub expr: Box, + } + + pub enum JSXElementName { + Ident(Ident), + JSXMemberExpr(JSXMemberExpr), + JSXNamespacedName(JSXNamespacedName), + } + + pub struct JSXOpeningElement { + pub name: JSXElementName, + + pub span: Span, + + pub attrs: Vec, + + pub self_closing: bool, + + pub type_args: Option, + } + + pub enum JSXAttrOrSpread { + JSXAttr(JSXAttr), + SpreadElement(SpreadElement), + } + + pub struct JSXClosingElement { + pub span: Span, + pub name: JSXElementName, + } + + pub struct JSXAttr { + pub span: Span, + pub name: JSXAttrName, + pub value: Option, + } + + pub enum JSXAttrName { + Ident(Ident), + JSXNamespacedName(JSXNamespacedName), + } + + pub enum JSXAttrValue { + Lit(Lit), + + JSXExprContainer(JSXExprContainer), + + JSXElement(Box), + + JSXFragment(JSXFragment), + } + + pub struct JSXText { + pub span: Span, + pub value: JsWord, + pub raw: JsWord, + } + + pub struct JSXElement { + pub span: Span, + pub opening: JSXOpeningElement, + pub children: Vec, + pub closing: Option, + } + + pub enum JSXElementChild { + JSXText(JSXText), + + JSXExprContainer(JSXExprContainer), + + JSXSpreadChild(JSXSpreadChild), + + JSXElement(Box), + + JSXFragment(JSXFragment), + } + + pub struct JSXFragment { + pub span: Span, + + pub opening: JSXOpeningFragment, + + pub children: Vec, + + pub closing: JSXClosingFragment, + } + + pub struct JSXOpeningFragment { + pub span: Span, + } + + pub struct JSXClosingFragment { + pub span: Span, + } + + pub use self::{ + class::{ + Class, ClassMember, ClassMethod, ClassProp, Constructor, Decorator, MethodKind, + PrivateMethod, PrivateProp, + }, + decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator}, + expr::{ + ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr, CallExpr, + ClassExpr, CondExpr, Expr, ExprOrSpread, ExprOrSuper, FnExpr, MemberExpr, MetaPropExpr, + NewExpr, ObjectLit, OptChainExpr, ParenExpr, PatOrExpr, PropOrSpread, SeqExpr, + SpreadElement, Super, TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, + YieldExpr, + }, + function::{Function, PatOrTsParamProp}, + ident::{Ident, IdentExt, PrivateName}, + jsx::{ + JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, + JSXClosingFragment, JSXElement, JSXElementChild, JSXElementName, JSXEmptyExpr, JSXExpr, + JSXExprContainer, JSXFragment, JSXMemberExpr, JSXNamespacedName, JSXObject, + JSXOpeningElement, JSXOpeningFragment, JSXSpreadChild, JSXText, + }, + lit::{BigInt, Bool, Lit, Null, Number, Regex, Str}, + module::{Module, ModuleItem, Program, Script}, + module_decl::{ + DefaultDecl, DefaultExportSpecifier, ExportAll, ExportDecl, ExportDefaultDecl, + ExportDefaultExpr, ExportSpecifier, ImportDecl, ImportDefault, ImportSpecific, + ImportSpecifier, ImportStarAs, ModuleDecl, NamedExport, NamedExportSpecifier, + NamespaceExportSpecifier, + }, + operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp}, + pat::{ + ArrayPat, AssignPat, AssignPatProp, KeyValuePatProp, ObjectPat, ObjectPatProp, Pat, + RestPat, + }, + prop::{ + AssignProp, ComputedPropName, GetterProp, KeyValueProp, MethodProp, Prop, PropName, + SetterProp, + }, + stmt::{ + BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt, EmptyStmt, + ExprStmt, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt, + SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, VarDeclOrPat, WhileStmt, + WithStmt, + }, + typescript::{ + Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl, + TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType, + TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment, + TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType, + TsImportEqualsDecl, TsImportType, TsIndexSignature, TsIndexedAccessType, TsInferType, + TsInterfaceBody, TsInterfaceDecl, TsIntersectionType, TsKeywordType, TsKeywordTypeKind, + TsLit, TsLitType, TsMappedType, TsMethodSignature, TsModuleBlock, TsModuleDecl, + TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl, TsNamespaceExportDecl, + TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam, TsParenthesizedType, + TsPropertySignature, TsQualifiedName, TsRestType, TsSignatureDecl, TsThisType, + TsThisTypeOrIdent, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, + TsTypeCastExpr, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, + TsTypeParam, TsTypeParamDecl, TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, + TsTypeQueryExpr, TsTypeRef, TsUnionOrIntersectionType, TsUnionType, + }, + }; + use swc_common::{ast_node, Span}; + + mod class; + mod decl; + mod expr; + mod function; + mod ident; + mod jsx; + mod lit; + mod macros; + mod module; + mod module_decl; + mod operators; + mod pat; + mod prop; + mod stmt; + mod typescript; + + pub struct Invalid { + pub span: Span, + } + use crate::jsx::JSXText; + use num_bigint::BigInt as BigIntValue; + use std::{ + fmt::{self, Display, Formatter}, + hash::{Hash, Hasher}, + mem, + }; + use swc_atoms::JsWord; + use swc_common::{ast_node, Span}; + + pub enum Lit { + Str(Str), + + Bool(Bool), + + Null(Null), + + Num(Number), + + BigInt(BigInt), + + Regex(Regex), + + JSXText(JSXText), + } + + pub struct BigInt { + pub span: Span, + pub value: BigIntValue, + } + + pub struct Str { + pub span: Span, + + pub value: JsWord, + + pub has_escape: bool, + } + impl Str { + pub fn is_empty(&self) -> bool { + self.value.is_empty() + } + } + + pub struct Bool { + pub span: Span, + pub value: bool, + } + + pub struct Null { + pub span: Span, + } + + pub struct Regex { + pub span: Span, + + pub exp: JsWord, + + pub flags: JsWord, + } + + pub struct Number { + pub span: Span, + pub value: f64, + } + + impl Eq for Number {} + + impl Hash for Number { + fn hash(&self, state: &mut H) { + fn integer_decode(val: f64) -> (u64, i16, i8) { + let bits: u64 = unsafe { mem::transmute(val) }; + let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; + let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; + let mantissa = if exponent == 0 { + (bits & 0xfffffffffffff) << 1 + } else { + (bits & 0xfffffffffffff) | 0x10000000000000 + }; + + exponent -= 1023 + 52; + (mantissa, exponent, sign) + } + + self.span.hash(state); + integer_decode(self.value).hash(state); + } + } + + impl Display for Number { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if self.value.is_infinite() { + if self.value.is_sign_positive() { + Display::fmt("Infinity", f) + } else { + Display::fmt("-Infinity", f) + } + } else { + Display::fmt(&self.value, f) + } + } + } + macro_rules! op { + (unary,"-") => { + $crate::UnaryOp::Minus + }; + (unary,"+") => { + $crate::UnaryOp::Plus + }; + ("!") => { + $crate::UnaryOp::Bang + }; + ("~") => { + $crate::UnaryOp::Tilde + }; + ("typeof") => { + $crate::UnaryOp::TypeOf + }; + ("void") => { + $crate::UnaryOp::Void + }; + ("delete") => { + $crate::UnaryOp::Delete + }; + + ("++") => { + $crate::UpdateOp::PlusPlus + }; + ("--") => { + $crate::UpdateOp::MinusMinus + }; + + ("==") => { + $crate::BinaryOp::EqEq + }; + ("!=") => { + $crate::BinaryOp::NotEq + }; + ("===") => { + $crate::BinaryOp::EqEqEq + }; + ("!==") => { + $crate::BinaryOp::NotEqEq + }; + ("<") => { + $crate::BinaryOp::Lt + }; + ("<=") => { + $crate::BinaryOp::LtEq + }; + (">") => { + $crate::BinaryOp::Gt + }; + (">=") => { + $crate::BinaryOp::GtEq + }; + ("<<") => { + $crate::BinaryOp::LShift + }; + (">>") => { + $crate::BinaryOp::RShift + }; + (">>>") => { + $crate::BinaryOp::ZeroFillRShift + }; + (bin,"+") => { + $crate::BinaryOp::Add + }; + (bin,"-") => { + $crate::BinaryOp::Sub + }; + ("*") => { + $crate::BinaryOp::Mul + }; + ("/") => { + $crate::BinaryOp::Div + }; + ("%") => { + $crate::BinaryOp::Mod + }; + ("|") => { + $crate::BinaryOp::BitOr + }; + ("^") => { + $crate::BinaryOp::BitXor + }; + ("&") => { + $crate::BinaryOp::BitAnd + }; + ("||") => { + $crate::BinaryOp::LogicalOr + }; + ("&&") => { + $crate::BinaryOp::LogicalAnd + }; + ("in") => { + $crate::BinaryOp::In + }; + ("instanceof") => { + $crate::BinaryOp::InstanceOf + }; + ("**") => { + $crate::BinaryOp::Exp + }; + ("??") => { + $crate::BinaryOp::NullishCoalescing + }; + + ("=") => { + $crate::AssignOp::Assign + }; + ("+=") => { + $crate::AssignOp::AddAssign + }; + ("-=") => { + $crate::AssignOp::SubAssign + }; + ("*=") => { + $crate::AssignOp::MulAssign + }; + ("/=") => { + $crate::AssignOp::DivAssign + }; + ("%=") => { + $crate::AssignOp::ModAssign + }; + ("<<=") => { + $crate::AssignOp::LShiftAssign + }; + (">>=") => { + $crate::AssignOp::RShiftAssign + }; + (">>>=") => { + $crate::AssignOp::ZeroFillRShiftAssign + }; + ("|=") => { + $crate::AssignOp::BitOrAssign + }; + ("^=") => { + $crate::AssignOp::BitXorAssign + }; + ("&=") => { + $crate::AssignOp::BitAndAssign + }; + ("**=") => { + $crate::AssignOp::ExpAssign + }; + } + + macro_rules! test_de { + ($name:ident, $T:path, $s:literal) => { + fn $name() { + let _var: $T = ::serde_json::from_str(&$s).expect("failed to parse json"); + } + }; + } + use crate::{module_decl::ModuleDecl, stmt::Stmt}; + use swc_atoms::JsWord; + use swc_common::{ast_node, Span}; + + pub enum Program { + Module(Module), + Script(Script), + } + + pub struct Module { + pub span: Span, + + pub body: Vec, + + pub shebang: Option, + } + + pub struct Script { + pub span: Span, + + pub body: Vec, + + pub shebang: Option, + } + + pub enum ModuleItem { + ModuleDecl(ModuleDecl), + Stmt(Stmt), + } + use crate::{ + decl::Decl, + expr::{ClassExpr, Expr, FnExpr}, + ident::Ident, + lit::Str, + typescript::{ + TsExportAssignment, TsImportEqualsDecl, TsInterfaceDecl, TsNamespaceExportDecl, + }, + }; + use swc_common::{ast_node, Span}; + + pub enum ModuleDecl { + Import(ImportDecl), + + ExportDecl(ExportDecl), + + ExportNamed(NamedExport), + + ExportDefaultDecl(ExportDefaultDecl), + + ExportDefaultExpr(ExportDefaultExpr), + + ExportAll(ExportAll), + + TsImportEquals(TsImportEqualsDecl), + + TsExportAssignment(TsExportAssignment), + + TsNamespaceExport(TsNamespaceExportDecl), + } + + pub struct ExportDefaultExpr { + pub span: Span, + + pub expr: Box, + } + + pub struct ExportDecl { + pub span: Span, + + pub decl: Decl, + } + + pub struct ImportDecl { + pub span: Span, + + pub specifiers: Vec, + + pub src: Str, + + pub type_only: bool, + } + + pub struct ExportAll { + pub span: Span, + + pub src: Str, + } + + pub struct NamedExport { + pub span: Span, + + pub specifiers: Vec, + + pub src: Option, + + pub type_only: bool, + } + + pub struct ExportDefaultDecl { + pub span: Span, + + pub decl: DefaultDecl, + } + + pub enum DefaultDecl { + Class(ClassExpr), + + Fn(FnExpr), + + TsInterfaceDecl(TsInterfaceDecl), + } + + pub enum ImportSpecifier { + Specific(ImportSpecific), + Default(ImportDefault), + Namespace(ImportStarAs), + } + + pub struct ImportDefault { + pub span: Span, -enum E { - StructLike { field: String }, - TupleLike(u32, u16), -} + pub local: Ident, + } + pub struct ImportStarAs { + pub span: Span, + + pub local: Ident, + } + pub struct ImportSpecific { + pub span: Span, + + pub local: Ident, + + pub imported: Option, + } + + pub enum ExportSpecifier { + Namespace(NamespaceExportSpecifier), + + Default(DefaultExportSpecifier), + + Named(NamedExportSpecifier), + } + + pub struct NamespaceExportSpecifier { + pub span: Span, + + pub name: Ident, + } + + pub struct DefaultExportSpecifier { + pub exported: Ident, + } + + pub struct NamedExportSpecifier { + pub span: Span, + pub orig: Ident, + pub exported: Option, + } + use enum_kind::Kind; + use string_enum::StringEnum; + use swc_common::Fold; + + pub enum BinaryOp { + EqEq, + NotEq, + EqEqEq, + NotEqEq, + Lt, + LtEq, + Gt, + GtEq, + LShift, + RShift, + ZeroFillRShift, + + Add, + Sub, + Mul, + Div, + Mod, + + BitOr, + BitXor, + BitAnd, + + LogicalOr, + + LogicalAnd, + + In, + InstanceOf, + + Exp, + + NullishCoalescing, + } + + pub enum AssignOp { + Assign, + AddAssign, + SubAssign, + MulAssign, + DivAssign, + ModAssign, + LShiftAssign, + RShiftAssign, + ZeroFillRShiftAssign, + BitOrAssign, + BitXorAssign, + BitAndAssign, + + ExpAssign, + } + + pub enum UpdateOp { + PlusPlus, + MinusMinus, + } + + pub enum UnaryOp { + Minus, + Plus, + Bang, + Tilde, + TypeOf, + Void, + Delete, + } + use crate::{expr::Expr, ident::Ident, prop::PropName, typescript::TsTypeAnn, Invalid}; + use swc_common::{ast_node, Span}; + + pub enum Pat { + Ident(Ident), + + Array(ArrayPat), + + Rest(RestPat), + + Object(ObjectPat), + + Assign(AssignPat), + + Invalid(Invalid), + + Expr(Box), + } + + pub struct ArrayPat { + pub span: Span, + + pub elems: Vec>, + + pub optional: bool, + + pub type_ann: Option, + } + + pub struct ObjectPat { + pub span: Span, + + pub props: Vec, + + pub optional: bool, + + pub type_ann: Option, + } + + pub struct AssignPat { + pub span: Span, + + pub left: Box, + + pub right: Box, + + pub type_ann: Option, + } + + pub struct RestPat { + pub span: Span, + + pub dot3_token: Span, + + pub arg: Box, + + pub type_ann: Option, + } + + pub enum ObjectPatProp { + KeyValue(KeyValuePatProp), + + Assign(AssignPatProp), + + Rest(RestPat), + } + + pub struct KeyValuePatProp { + pub key: PropName, + + pub value: Box, + } + pub struct AssignPatProp { + pub span: Span, + pub key: Ident, + + pub value: Option>, + } + use crate::{ + expr::Expr, + function::Function, + ident::Ident, + lit::{Number, Str}, + pat::Pat, + stmt::BlockStmt, + typescript::TsTypeAnn, + }; + use swc_common::{ast_node, Span}; + + pub enum Prop { + Shorthand(Ident), + + KeyValue(KeyValueProp), + + Assign(AssignProp), + + Getter(GetterProp), + + Setter(SetterProp), + + Method(MethodProp), + } + + pub struct KeyValueProp { + pub key: PropName, + + pub value: Box, + } + + pub struct AssignProp { + pub key: Ident, + pub value: Box, + } + + pub struct GetterProp { + pub span: Span, + pub key: PropName, + pub type_ann: Option, + pub body: Option, + } + pub struct SetterProp { + pub span: Span, + pub key: PropName, + pub param: Pat, + pub body: Option, + } + pub struct MethodProp { + pub key: PropName, + + pub function: Function, + } + + pub enum PropName { + Ident(Ident), + Str(Str), + Num(Number), + Computed(ComputedPropName), + } + + pub struct ComputedPropName { + pub span: Span, + pub expr: Box, + } + use crate::{ + decl::{Decl, VarDecl}, + expr::Expr, + ident::Ident, + pat::Pat, + }; + use swc_common::{ast_node, Span}; + + pub struct BlockStmt { + pub span: Span, + + pub stmts: Vec, + } + + pub enum Stmt { + Block(BlockStmt), + + Empty(EmptyStmt), + + Debugger(DebuggerStmt), + + With(WithStmt), + + Return(ReturnStmt), + + Labeled(LabeledStmt), + + Break(BreakStmt), + + Continue(ContinueStmt), + + If(IfStmt), + + Switch(SwitchStmt), + + Throw(ThrowStmt), + + Try(TryStmt), + + While(WhileStmt), + + DoWhile(DoWhileStmt), + + For(ForStmt), + + ForIn(ForInStmt), + + ForOf(ForOfStmt), + + Decl(Decl), + + Expr(ExprStmt), + } + + pub struct ExprStmt { + pub span: Span, + pub expr: Box, + } + + pub struct EmptyStmt { + pub span: Span, + } + + pub struct DebuggerStmt { + pub span: Span, + } + + pub struct WithStmt { + pub span: Span, + pub obj: Box, + pub body: Box, + } + + pub struct ReturnStmt { + pub span: Span, + pub arg: Option>, + } + + pub struct LabeledStmt { + pub span: Span, + pub label: Ident, + pub body: Box, + } + + pub struct BreakStmt { + pub span: Span, + pub label: Option, + } + + pub struct ContinueStmt { + pub span: Span, + pub label: Option, + } + + pub struct IfStmt { + pub span: Span, + pub test: Box, + + pub cons: Box, + + pub alt: Option>, + } + + pub struct SwitchStmt { + pub span: Span, + pub discriminant: Box, + pub cases: Vec, + } + + pub struct ThrowStmt { + pub span: Span, + pub arg: Box, + } + + pub struct TryStmt { + pub span: Span, + + pub block: BlockStmt, + + pub handler: Option, + + pub finalizer: Option, + } + + pub struct WhileStmt { + pub span: Span, + pub test: Box, + pub body: Box, + } + + pub struct DoWhileStmt { + pub span: Span, + pub test: Box, + pub body: Box, + } + + pub struct ForStmt { + pub span: Span, + + pub init: Option, + + pub test: Option>, + + pub update: Option>, + + pub body: Box, + } + + pub struct ForInStmt { + pub span: Span, + pub left: VarDeclOrPat, + pub right: Box, + pub body: Box, + } + + pub struct ForOfStmt { + pub span: Span, + pub await_token: Option, + pub left: VarDeclOrPat, + pub right: Box, + pub body: Box, + } + + pub struct SwitchCase { + pub span: Span, + + pub test: Option>, + + pub cons: Vec, + } + + pub struct CatchClause { + pub span: Span, + pub param: Option, + + pub body: BlockStmt, + } + + pub enum VarDeclOrPat { + VarDecl(VarDecl), + + Pat(Pat), + } + + pub enum VarDeclOrExpr { + VarDecl(VarDecl), + + Expr(Box), + } + use crate::{ + class::Decorator, + expr::Expr, + ident::Ident, + lit::{Bool, Number, Str}, + module::ModuleItem, + pat::{ArrayPat, AssignPat, ObjectPat, RestPat}, + }; + use serde::{ + de::{self, Unexpected, Visitor}, + Deserialize, Deserializer, Serialize, + }; + use std::fmt; + use string_enum::StringEnum; + use swc_common::{ast_node, Fold, Span}; + + pub struct TsTypeAnn { + pub span: Span, + pub type_ann: Box, + } + + pub struct TsTypeParamDecl { + pub span: Span, + pub params: Vec, + } + + pub struct TsTypeParam { + pub span: Span, + pub name: Ident, + + pub constraint: Option>, + + pub default: Option>, + } + + pub struct TsTypeParamInstantiation { + pub span: Span, + pub params: Vec>, + } + + pub struct TsTypeCastExpr { + pub span: Span, + pub expr: Box, + pub type_ann: TsTypeAnn, + } -define!( - S { - field: String, - field2: u64 - }, - E(StructLike { field: String }, TupleLike(u32, u16)), - String, - u64, - u32, - u16 -); + pub struct TsParamProp { + pub span: Span, + pub decorators: Vec, + pub accessibility: Option, + pub readonly: bool, + pub param: TsParamPropParam, + } + + pub enum TsParamPropParam { + Ident(Ident), + + Assign(AssignPat), + } + + pub struct TsQualifiedName { + pub left: TsEntityName, + pub right: Ident, + } + + pub enum TsEntityName { + TsQualifiedName(Box), + + Ident(Ident), + } + + pub enum TsSignatureDecl { + TsCallSignatureDecl(TsCallSignatureDecl), + + TsConstructSignatureDecl(TsConstructSignatureDecl), + + TsMethodSignature(TsMethodSignature), + + TsFnType(TsFnType), + + TsConstructorType(TsConstructorType), + } + + pub enum TsTypeElement { + TsCallSignatureDecl(TsCallSignatureDecl), + + TsConstructSignatureDecl(TsConstructSignatureDecl), + + TsPropertySignature(TsPropertySignature), + + TsMethodSignature(TsMethodSignature), + + TsIndexSignature(TsIndexSignature), + } + + pub struct TsCallSignatureDecl { + pub span: Span, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + + pub struct TsConstructSignatureDecl { + pub span: Span, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + + pub struct TsPropertySignature { + pub span: Span, + pub readonly: bool, + pub key: Box, + pub computed: bool, + pub optional: bool, + pub init: Option>, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + + pub struct TsMethodSignature { + pub span: Span, + pub readonly: bool, + pub key: Box, + pub computed: bool, + pub optional: bool, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + + pub struct TsIndexSignature { + pub params: Vec, + pub type_ann: Option, + + pub readonly: bool, + pub span: Span, + } + + pub enum TsType { + TsKeywordType(TsKeywordType), + + TsThisType(TsThisType), + + TsFnOrConstructorType(TsFnOrConstructorType), + + TsTypeRef(TsTypeRef), + + TsTypeQuery(TsTypeQuery), + + TsTypeLit(TsTypeLit), + + TsArrayType(TsArrayType), + + TsTupleType(TsTupleType), + + TsOptionalType(TsOptionalType), + + TsRestType(TsRestType), + + TsUnionOrIntersectionType(TsUnionOrIntersectionType), + + TsConditionalType(TsConditionalType), + + TsInferType(TsInferType), + + TsParenthesizedType(TsParenthesizedType), + + TsTypeOperator(TsTypeOperator), + + TsIndexedAccessType(TsIndexedAccessType), + + TsMappedType(TsMappedType), + + TsLitType(TsLitType), + + TsTypePredicate(TsTypePredicate), + + TsImportType(TsImportType), + } + + pub enum TsFnOrConstructorType { + TsFnType(TsFnType), + TsConstructorType(TsConstructorType), + } + + impl From for TsType { + fn from(t: TsFnType) -> Self { + TsFnOrConstructorType::TsFnType(t).into() + } + } + + impl From for TsType { + fn from(t: TsConstructorType) -> Self { + TsFnOrConstructorType::TsConstructorType(t).into() + } + } + + impl From for TsType { + fn from(t: TsUnionType) -> Self { + TsUnionOrIntersectionType::TsUnionType(t).into() + } + } + + impl From for TsType { + fn from(t: TsIntersectionType) -> Self { + TsUnionOrIntersectionType::TsIntersectionType(t).into() + } + } + + pub struct TsKeywordType { + pub span: Span, + pub kind: TsKeywordTypeKind, + } + + pub enum TsKeywordTypeKind { + TsAnyKeyword, + + TsUnknownKeyword, + + TsNumberKeyword, + + TsObjectKeyword, + + TsBooleanKeyword, + + TsBigIntKeyword, + + TsStringKeyword, + + TsSymbolKeyword, + + TsVoidKeyword, + + TsUndefinedKeyword, + + TsNullKeyword, + + TsNeverKeyword, + } + + pub struct TsThisType { + pub span: Span, + } + + pub enum TsFnParam { + Ident(Ident), + + Array(ArrayPat), + + Rest(RestPat), + + Object(ObjectPat), + } + + pub struct TsFnType { + pub span: Span, + pub params: Vec, + + pub type_params: Option, + pub type_ann: TsTypeAnn, + } + + pub struct TsConstructorType { + pub span: Span, + pub params: Vec, + pub type_params: Option, + pub type_ann: TsTypeAnn, + } + + pub struct TsTypeRef { + pub span: Span, + pub type_name: TsEntityName, + pub type_params: Option, + } + + pub struct TsTypePredicate { + pub span: Span, + pub asserts: bool, + pub param_name: TsThisTypeOrIdent, + pub type_ann: Option, + } + + pub enum TsThisTypeOrIdent { + TsThisType(TsThisType), + + Ident(Ident), + } + + pub struct TsTypeQuery { + pub span: Span, + pub expr_name: TsTypeQueryExpr, + } + + pub enum TsTypeQueryExpr { + TsEntityName(TsEntityName), + Import(TsImportType), + } + + pub struct TsImportType { + pub span: Span, + pub arg: Str, + pub qualifier: Option, + pub type_args: Option, + } + + pub struct TsTypeLit { + pub span: Span, + pub members: Vec, + } + + pub struct TsArrayType { + pub span: Span, + pub elem_type: Box, + } + + pub struct TsTupleType { + pub span: Span, + pub elem_types: Vec>, + } + + pub struct TsOptionalType { + pub span: Span, + pub type_ann: Box, + } + + pub struct TsRestType { + pub span: Span, + pub type_ann: Box, + } + + pub enum TsUnionOrIntersectionType { + TsUnionType(TsUnionType), + + TsIntersectionType(TsIntersectionType), + } + + pub struct TsUnionType { + pub span: Span, + pub types: Vec>, + } + + pub struct TsIntersectionType { + pub span: Span, + pub types: Vec>, + } + + pub struct TsConditionalType { + pub span: Span, + pub check_type: Box, + pub extends_type: Box, + pub true_type: Box, + pub false_type: Box, + } + + pub struct TsInferType { + pub span: Span, + pub type_param: TsTypeParam, + } + + pub struct TsParenthesizedType { + pub span: Span, + pub type_ann: Box, + } + + pub struct TsTypeOperator { + pub span: Span, + pub op: TsTypeOperatorOp, + pub type_ann: Box, + } + + pub enum TsTypeOperatorOp { + KeyOf, + Unique, + ReadOnly, + } + + pub struct TsIndexedAccessType { + pub span: Span, + pub readonly: bool, + pub obj_type: Box, + pub index_type: Box, + } + + pub enum TruePlusMinus { + True, + Plus, + Minus, + } + + impl Serialize for TruePlusMinus { + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { + match *self { + TruePlusMinus::True => serializer.serialize_bool(true), + TruePlusMinus::Plus => serializer.serialize_str("+"), + TruePlusMinus::Minus => serializer.serialize_str("-"), + } + } + } + + impl<'de> Deserialize<'de> for TruePlusMinus { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TruePlusMinusVisitor; + + impl<'de> Visitor<'de> for TruePlusMinusVisitor { + type Value = TruePlusMinus; + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("one of '+', '-', true") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + match value { + "+" => Ok(TruePlusMinus::Plus), + "-" => Ok(TruePlusMinus::Minus), + "true" => Ok(TruePlusMinus::True), + _ => Err(de::Error::invalid_value(Unexpected::Str(value), &self)), + } + } + + fn visit_bool(self, value: bool) -> Result + where + E: de::Error, + { + if value { + Ok(TruePlusMinus::True) + } else { + Err(de::Error::invalid_value(Unexpected::Bool(value), &self)) + } + } + } + + deserializer.deserialize_any(TruePlusMinusVisitor) + } + } + + pub struct TsMappedType { + pub span: Span, + pub readonly: Option, + pub type_param: TsTypeParam, + pub optional: Option, + pub type_ann: Option>, + } + + pub struct TsLitType { + pub span: Span, + pub lit: TsLit, + } + + pub enum TsLit { + Number(Number), + + Str(Str), + + Bool(Bool), + } + + pub struct TsInterfaceDecl { + pub span: Span, + pub id: Ident, + pub declare: bool, + pub type_params: Option, + pub extends: Vec, + pub body: TsInterfaceBody, + } + + pub struct TsInterfaceBody { + pub span: Span, + pub body: Vec, + } + + pub struct TsExprWithTypeArgs { + pub span: Span, + pub expr: TsEntityName, + pub type_args: Option, + } + + pub struct TsTypeAliasDecl { + pub span: Span, + pub declare: bool, + pub id: Ident, + pub type_params: Option, + pub type_ann: Box, + } + + pub struct TsEnumDecl { + pub span: Span, + pub declare: bool, + pub is_const: bool, + pub id: Ident, + pub members: Vec, + } + + pub struct TsEnumMember { + pub span: Span, + pub id: TsEnumMemberId, + pub init: Option>, + } + + pub enum TsEnumMemberId { + Ident(Ident), + + Str(Str), + } + + pub struct TsModuleDecl { + pub span: Span, + pub declare: bool, + pub global: bool, + pub id: TsModuleName, + pub body: Option, + } + + pub enum TsNamespaceBody { + TsModuleBlock(TsModuleBlock), + + TsNamespaceDecl(TsNamespaceDecl), + } + + pub struct TsModuleBlock { + pub span: Span, + pub body: Vec, + } + + pub struct TsNamespaceDecl { + pub span: Span, + pub declare: bool, + pub global: bool, + pub id: Ident, + pub body: Box, + } + + pub enum TsModuleName { + Ident(Ident), + + Str(Str), + } + + pub struct TsImportEqualsDecl { + pub span: Span, + pub declare: bool, + pub is_export: bool, + pub id: Ident, + pub module_ref: TsModuleRef, + } + + pub enum TsModuleRef { + TsEntityName(TsEntityName), + + TsExternalModuleRef(TsExternalModuleRef), + } + + pub struct TsExternalModuleRef { + pub span: Span, + pub expr: Str, + } + + pub struct TsExportAssignment { + pub span: Span, + pub expr: Box, + } + + pub struct TsNamespaceExportDecl { + pub span: Span, + pub id: Ident, + } + + pub struct TsAsExpr { + pub span: Span, + pub expr: Box, + pub type_ann: Box, + } + + pub struct TsTypeAssertion { + pub span: Span, + pub expr: Box, + pub type_ann: Box, + } + + pub struct TsNonNullExpr { + pub span: Span, + pub expr: Box, + } + + pub enum Accessibility { + Public, + Protected, + Private, + } + + pub struct TsConstAssertion { + pub span: Span, + pub expr: Box, + } +} From c687c494acad83ba610c1e7235540aa10de373e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 20:01:09 +0900 Subject: [PATCH 14/32] More work --- ecmascript/visit/macros/src/lib.rs | 51 +-- ecmascript/visit/src/lib.rs | 562 ----------------------------- 2 files changed, 27 insertions(+), 586 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index ee2e3af60ca9..13162b418d8f 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -266,8 +266,8 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { let arm = make_arm_from_struct( &q!( Vars { - Enum: e.ident, - Variant: variant.ident + Enum: &e.ident, + Variant: &variant.ident }, { Enum::Variant } ) @@ -301,26 +301,6 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { } } -struct Input { - /// - /// ``` - /// Struct{ fields } - /// ``` - /// - /// ``` - /// Enum([Variant1, StructLike { fields }]) - /// ``` - args: Punctuated, -} - -impl Parse for Input { - fn parse(input: ParseStream) -> Result { - Ok(Self { - args: Punctuated::parse_separated_nonempty(input)?, - }) - } -} - fn method_sig(type_name: &Ident) -> Signature { Signature { constness: None, @@ -346,6 +326,29 @@ fn method_sig(type_name: &Ident) -> Signature { } } -fn method_name(v: &Type) -> String { - format!("visit_{}", v.to_snake_case()) +fn method_name(v: &Type) -> Ident { + fn handle(v: &str) -> String { + format!("visit_{}", v.to_snake_case()) + } + + match v { + Type::Array(_) => unimplemented!("type: array type"), + Type::BareFn(_) => unimplemented!("type: fn type"), + Type::Group(_) => unimplemented!("type: group type"), + Type::ImplTrait(_) => unimplemented!("type: impl trait"), + Type::Infer(_) => unreachable!("infer type"), + Type::Macro(_) => unimplemented!("type: macro"), + Type::Never(_) => unreachable!("never type"), + Type::Paren(ty) => return method_name(&ty.elem), + Type::Path(p) => p.path.segments.last().unwrap().ident.new_ident_with(handle), + Type::Ptr(_) => unimplemented!("type: pointer"), + Type::Reference(ty) => { + return method_name(&ty.elem); + } + Type::Slice(_) => unimplemented!("type: slice"), + Type::TraitObject(_) => unimplemented!("type: trait object"), + Type::Tuple(_) => unimplemented!("type: trait tuple"), + Type::Verbatim(_) => unimplemented!("type: verbatim"), + _ => unimplemented!("Unknown type: {:?}", v), + } } diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index 32d354bfe40c..4284b697f24d 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -27,7 +27,6 @@ define!({ } }); -#[visit] mod types { use crate::{ expr::Expr, @@ -213,24 +212,6 @@ mod types { pub definite: bool, } - use crate::{ - class::Class, - function::Function, - ident::{Ident, PrivateName}, - jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName}, - lit::{Bool, Lit, Number, Str}, - operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp}, - pat::Pat, - prop::Prop, - stmt::BlockStmt, - typescript::{ - TsAsExpr, TsConstAssertion, TsNonNullExpr, TsTypeAnn, TsTypeAssertion, TsTypeCastExpr, - TsTypeParamDecl, TsTypeParamInstantiation, - }, - Invalid, - }; - use serde::{self, Deserialize, Serialize}; - use swc_common::{ast_node, Fold, Span, Spanned, DUMMY_SP}; pub enum Expr { This(ThisExpr), @@ -514,16 +495,6 @@ mod types { pub expr: Box, } - impl Spanned for ExprOrSpread { - fn span(&self) -> Span { - let expr = self.expr.span(); - match self.spread { - Some(spread) => expr.with_lo(spread.lo()), - None => expr, - } - } - } - pub enum BlockStmtOrExpr { BlockStmt(BlockStmt), Expr(Box), @@ -534,88 +505,11 @@ mod types { Pat(Box), } - impl From for Expr { - fn from(value: bool) -> Self { - Expr::Lit(Lit::Bool(Bool { - span: DUMMY_SP, - value, - })) - } - } - - impl From for Expr { - fn from(value: f64) -> Self { - Expr::Lit(Lit::Num(Number { - span: DUMMY_SP, - value, - })) - } - } - - impl From for Expr { - fn from(v: Bool) -> Self { - Expr::Lit(Lit::Bool(v)) - } - } - - impl From for Expr { - fn from(v: Number) -> Self { - Expr::Lit(Lit::Num(v)) - } - } - - impl From for Expr { - fn from(v: Str) -> Self { - Expr::Lit(Lit::Str(v)) - } - } - pub struct OptChainExpr { pub span: Span, pub expr: Box, } - test_de!( - jsx_element, - JSXElement, - r#"{ -"type": "JSXElement", -"span": { -"start": 0, -"end": 5, -"ctxt": 0 -}, -"opening": { -"type": "JSXOpeningElement", -"name": { -"type": "Identifier", -"span": { -"start": 1, -"end": 2, -"ctxt": 0 -}, -"value": "a", -"optional": false -}, -"span": { -"start": 1, -"end": 5, -"ctxt": 0 -}, -"selfClosing": true -}, -"children": [], -"closing": null -}"# - ); - use crate::{ - class::Decorator, - pat::Pat, - stmt::BlockStmt, - typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl}, - }; - use swc_common::{ast_node, Span}; - pub struct Function { pub params: Vec, @@ -638,9 +532,6 @@ mod types { TsParamProp(TsParamProp), Pat(Pat), } - use crate::typescript::TsTypeAnn; - use swc_atoms::JsWord; - use swc_common::{ast_node, Span}; pub struct Ident { pub span: Span, @@ -654,131 +545,6 @@ mod types { pub id: Ident, } - impl AsRef for Ident { - fn as_ref(&self) -> &str { - &self.sym - } - } - - impl Ident { - pub const fn new(sym: JsWord, span: Span) -> Self { - Ident { - span, - sym, - type_ann: None, - optional: false, - } - } - } - - pub trait IdentExt: AsRef { - fn is_reserved_for_es3(&self) -> bool { - [ - "abstract", - "boolean", - "break", - "byte", - "case", - "catch", - "char", - "class", - "const", - "continue", - "debugger", - "default", - "delete", - "do", - "double", - "else", - "enum", - "export", - "extends", - "false", - "final", - "finally", - "float", - "for", - "function", - "goto", - "if", - "implements", - "import", - "in", - "instanceof", - "int", - "interface", - "long", - "native", - "new", - "null", - "package", - "private", - "protected", - "public", - "return", - "short", - "static", - "super", - "switch", - "synchronized", - "this", - "throw", - "throws", - "transient", - "true", - "try", - "typeof", - "var", - "void", - "volatile", - "while", - "with", - ] - .contains(&self.as_ref()) - } - - fn is_reserved_only_for_es3(&self) -> bool { - [ - "abstract", - "boolean", - "byte", - "char", - "double", - "enum", - "final", - "float", - "goto", - "implements", - "int", - "interface", - "long", - "native", - "package", - "private", - "protected", - "public", - "short", - "static", - "synchronized", - "throws", - "transient", - "volatile", - ] - .contains(&self.as_ref()) - } - } - - impl IdentExt for JsWord {} - impl IdentExt for Ident {} - use crate::{ - expr::{Expr, SpreadElement}, - ident::Ident, - lit::Lit, - typescript::TsTypeParamInstantiation, - }; - use swc_atoms::JsWord; - use swc_common::{ast_node, Span}; - pub enum JSXObject { JSXMemberExpr(Box), Ident(Ident), @@ -906,97 +672,9 @@ mod types { pub span: Span, } - pub use self::{ - class::{ - Class, ClassMember, ClassMethod, ClassProp, Constructor, Decorator, MethodKind, - PrivateMethod, PrivateProp, - }, - decl::{ClassDecl, Decl, FnDecl, VarDecl, VarDeclKind, VarDeclarator}, - expr::{ - ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr, CallExpr, - ClassExpr, CondExpr, Expr, ExprOrSpread, ExprOrSuper, FnExpr, MemberExpr, MetaPropExpr, - NewExpr, ObjectLit, OptChainExpr, ParenExpr, PatOrExpr, PropOrSpread, SeqExpr, - SpreadElement, Super, TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, - YieldExpr, - }, - function::{Function, PatOrTsParamProp}, - ident::{Ident, IdentExt, PrivateName}, - jsx::{ - JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, - JSXClosingFragment, JSXElement, JSXElementChild, JSXElementName, JSXEmptyExpr, JSXExpr, - JSXExprContainer, JSXFragment, JSXMemberExpr, JSXNamespacedName, JSXObject, - JSXOpeningElement, JSXOpeningFragment, JSXSpreadChild, JSXText, - }, - lit::{BigInt, Bool, Lit, Null, Number, Regex, Str}, - module::{Module, ModuleItem, Program, Script}, - module_decl::{ - DefaultDecl, DefaultExportSpecifier, ExportAll, ExportDecl, ExportDefaultDecl, - ExportDefaultExpr, ExportSpecifier, ImportDecl, ImportDefault, ImportSpecific, - ImportSpecifier, ImportStarAs, ModuleDecl, NamedExport, NamedExportSpecifier, - NamespaceExportSpecifier, - }, - operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp}, - pat::{ - ArrayPat, AssignPat, AssignPatProp, KeyValuePatProp, ObjectPat, ObjectPatProp, Pat, - RestPat, - }, - prop::{ - AssignProp, ComputedPropName, GetterProp, KeyValueProp, MethodProp, Prop, PropName, - SetterProp, - }, - stmt::{ - BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt, EmptyStmt, - ExprStmt, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt, - SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, VarDeclOrPat, WhileStmt, - WithStmt, - }, - typescript::{ - Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl, - TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType, - TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment, - TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType, - TsImportEqualsDecl, TsImportType, TsIndexSignature, TsIndexedAccessType, TsInferType, - TsInterfaceBody, TsInterfaceDecl, TsIntersectionType, TsKeywordType, TsKeywordTypeKind, - TsLit, TsLitType, TsMappedType, TsMethodSignature, TsModuleBlock, TsModuleDecl, - TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl, TsNamespaceExportDecl, - TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam, TsParenthesizedType, - TsPropertySignature, TsQualifiedName, TsRestType, TsSignatureDecl, TsThisType, - TsThisTypeOrIdent, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, - TsTypeCastExpr, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, - TsTypeParam, TsTypeParamDecl, TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, - TsTypeQueryExpr, TsTypeRef, TsUnionOrIntersectionType, TsUnionType, - }, - }; - use swc_common::{ast_node, Span}; - - mod class; - mod decl; - mod expr; - mod function; - mod ident; - mod jsx; - mod lit; - mod macros; - mod module; - mod module_decl; - mod operators; - mod pat; - mod prop; - mod stmt; - mod typescript; - pub struct Invalid { pub span: Span, } - use crate::jsx::JSXText; - use num_bigint::BigInt as BigIntValue; - use std::{ - fmt::{self, Display, Formatter}, - hash::{Hash, Hasher}, - mem, - }; - use swc_atoms::JsWord; - use swc_common::{ast_node, Span}; pub enum Lit { Str(Str), @@ -1026,11 +704,6 @@ mod types { pub has_escape: bool, } - impl Str { - pub fn is_empty(&self) -> bool { - self.value.is_empty() - } - } pub struct Bool { pub span: Span, @@ -1054,200 +727,6 @@ mod types { pub value: f64, } - impl Eq for Number {} - - impl Hash for Number { - fn hash(&self, state: &mut H) { - fn integer_decode(val: f64) -> (u64, i16, i8) { - let bits: u64 = unsafe { mem::transmute(val) }; - let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 }; - let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16; - let mantissa = if exponent == 0 { - (bits & 0xfffffffffffff) << 1 - } else { - (bits & 0xfffffffffffff) | 0x10000000000000 - }; - - exponent -= 1023 + 52; - (mantissa, exponent, sign) - } - - self.span.hash(state); - integer_decode(self.value).hash(state); - } - } - - impl Display for Number { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if self.value.is_infinite() { - if self.value.is_sign_positive() { - Display::fmt("Infinity", f) - } else { - Display::fmt("-Infinity", f) - } - } else { - Display::fmt(&self.value, f) - } - } - } - macro_rules! op { - (unary,"-") => { - $crate::UnaryOp::Minus - }; - (unary,"+") => { - $crate::UnaryOp::Plus - }; - ("!") => { - $crate::UnaryOp::Bang - }; - ("~") => { - $crate::UnaryOp::Tilde - }; - ("typeof") => { - $crate::UnaryOp::TypeOf - }; - ("void") => { - $crate::UnaryOp::Void - }; - ("delete") => { - $crate::UnaryOp::Delete - }; - - ("++") => { - $crate::UpdateOp::PlusPlus - }; - ("--") => { - $crate::UpdateOp::MinusMinus - }; - - ("==") => { - $crate::BinaryOp::EqEq - }; - ("!=") => { - $crate::BinaryOp::NotEq - }; - ("===") => { - $crate::BinaryOp::EqEqEq - }; - ("!==") => { - $crate::BinaryOp::NotEqEq - }; - ("<") => { - $crate::BinaryOp::Lt - }; - ("<=") => { - $crate::BinaryOp::LtEq - }; - (">") => { - $crate::BinaryOp::Gt - }; - (">=") => { - $crate::BinaryOp::GtEq - }; - ("<<") => { - $crate::BinaryOp::LShift - }; - (">>") => { - $crate::BinaryOp::RShift - }; - (">>>") => { - $crate::BinaryOp::ZeroFillRShift - }; - (bin,"+") => { - $crate::BinaryOp::Add - }; - (bin,"-") => { - $crate::BinaryOp::Sub - }; - ("*") => { - $crate::BinaryOp::Mul - }; - ("/") => { - $crate::BinaryOp::Div - }; - ("%") => { - $crate::BinaryOp::Mod - }; - ("|") => { - $crate::BinaryOp::BitOr - }; - ("^") => { - $crate::BinaryOp::BitXor - }; - ("&") => { - $crate::BinaryOp::BitAnd - }; - ("||") => { - $crate::BinaryOp::LogicalOr - }; - ("&&") => { - $crate::BinaryOp::LogicalAnd - }; - ("in") => { - $crate::BinaryOp::In - }; - ("instanceof") => { - $crate::BinaryOp::InstanceOf - }; - ("**") => { - $crate::BinaryOp::Exp - }; - ("??") => { - $crate::BinaryOp::NullishCoalescing - }; - - ("=") => { - $crate::AssignOp::Assign - }; - ("+=") => { - $crate::AssignOp::AddAssign - }; - ("-=") => { - $crate::AssignOp::SubAssign - }; - ("*=") => { - $crate::AssignOp::MulAssign - }; - ("/=") => { - $crate::AssignOp::DivAssign - }; - ("%=") => { - $crate::AssignOp::ModAssign - }; - ("<<=") => { - $crate::AssignOp::LShiftAssign - }; - (">>=") => { - $crate::AssignOp::RShiftAssign - }; - (">>>=") => { - $crate::AssignOp::ZeroFillRShiftAssign - }; - ("|=") => { - $crate::AssignOp::BitOrAssign - }; - ("^=") => { - $crate::AssignOp::BitXorAssign - }; - ("&=") => { - $crate::AssignOp::BitAndAssign - }; - ("**=") => { - $crate::AssignOp::ExpAssign - }; - } - - macro_rules! test_de { - ($name:ident, $T:path, $s:literal) => { - fn $name() { - let _var: $T = ::serde_json::from_str(&$s).expect("failed to parse json"); - } - }; - } - use crate::{module_decl::ModuleDecl, stmt::Stmt}; - use swc_atoms::JsWord; - use swc_common::{ast_node, Span}; - pub enum Program { Module(Module), Script(Script), @@ -1273,16 +752,6 @@ mod types { ModuleDecl(ModuleDecl), Stmt(Stmt), } - use crate::{ - decl::Decl, - expr::{ClassExpr, Expr, FnExpr}, - ident::Ident, - lit::Str, - typescript::{ - TsExportAssignment, TsImportEqualsDecl, TsInterfaceDecl, TsNamespaceExportDecl, - }, - }; - use swc_common::{ast_node, Span}; pub enum ModuleDecl { Import(ImportDecl), @@ -1403,9 +872,6 @@ mod types { pub orig: Ident, pub exported: Option, } - use enum_kind::Kind; - use string_enum::StringEnum; - use swc_common::Fold; pub enum BinaryOp { EqEq, @@ -1473,8 +939,6 @@ mod types { Void, Delete, } - use crate::{expr::Expr, ident::Ident, prop::PropName, typescript::TsTypeAnn, Invalid}; - use swc_common::{ast_node, Span}; pub enum Pat { Ident(Ident), @@ -1551,16 +1015,6 @@ mod types { pub value: Option>, } - use crate::{ - expr::Expr, - function::Function, - ident::Ident, - lit::{Number, Str}, - pat::Pat, - stmt::BlockStmt, - typescript::TsTypeAnn, - }; - use swc_common::{ast_node, Span}; pub enum Prop { Shorthand(Ident), @@ -1622,7 +1076,6 @@ mod types { ident::Ident, pat::Pat, }; - use swc_common::{ast_node, Span}; pub struct BlockStmt { pub span: Span, @@ -1805,21 +1258,6 @@ mod types { Expr(Box), } - use crate::{ - class::Decorator, - expr::Expr, - ident::Ident, - lit::{Bool, Number, Str}, - module::ModuleItem, - pat::{ArrayPat, AssignPat, ObjectPat, RestPat}, - }; - use serde::{ - de::{self, Unexpected, Visitor}, - Deserialize, Deserializer, Serialize, - }; - use std::fmt; - use string_enum::StringEnum; - use swc_common::{ast_node, Fold, Span}; pub struct TsTypeAnn { pub span: Span, From a451ca209655fcefbe81e18afc7478741c2e6128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 20:19:19 +0900 Subject: [PATCH 15/32] Macro for enum works --- ecmascript/visit/macros/src/lib.rs | 110 +- ecmascript/visit/src/lib.rs | 3590 ++++++++++++++-------------- 2 files changed, 1876 insertions(+), 1824 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 13162b418d8f..e682e17ed5c8 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -1,16 +1,17 @@ use inflector::Inflector; use pmutil::{q, smart_quote, IdentExt, ToTokensExt}; use proc_macro2::Ident; -use swc_macros_common::def_site; +use swc_macros_common::{call_site, def_site}; use syn::{ parse::{Parse, ParseBuffer, ParseStream}, parse_quote::parse, punctuated::Punctuated, spanned::Spanned, + token::Token, Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, FieldPat, FieldValue, - Fields, ImplItem, ImplItemMethod, Item, ItemEnum, ItemImpl, ItemMod, ItemStruct, ItemTrait, - Member, Pat, PatStruct, Path, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMacro, - TraitItemMethod, Type, Variant, VisPublic, Visibility, + Fields, GenericArgument, ImplItem, ImplItemMethod, Index, Item, ItemEnum, ItemImpl, ItemMod, + ItemStruct, ItemTrait, Member, Pat, PatStruct, Path, PathArguments, ReturnType, Signature, + Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, Type, Variant, VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -133,17 +134,47 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { let mut stmts = vec![]; let mut fields: Punctuated = Default::default(); - for field in variant { + for (i, field) in variant.iter().enumerate() { let ty = &field.ty; let visit_name = method_name(&ty); + let binding_ident = field + .ident + .clone() + .unwrap_or_else(|| Ident::new(&format!("_{}", i), call_site())); - let stmt = q!(Vars { field, visit_name }, { - self.visit_name(field, n as _); - }) + let stmt = q!( + Vars { + binding_ident: &binding_ident, + visit_name + }, + { + self.visit_name(binding_ident, n as _); + } + ) .parse(); stmts.push(stmt); - fields.push(q!(Vars { field }, { field }).parse()); + if field.ident.is_some() { + fields.push( + q!( + Vars { + field: &binding_ident + }, + { field } + ) + .parse(), + ); + } else { + fields.push(FieldValue { + attrs: vec![], + member: Member::Unnamed(Index { + index: i as _, + span: path.span(), + }), + colon_token: Some(def_site()), + expr: q!(Vars { binding_ident }, { binding_ident }).parse(), + }); + } } let block = Block { @@ -153,7 +184,7 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { Arm { attrs: vec![], - pat: q!(Vars { Path: path, fields }, { Path::Variant { fields } }).parse(), + pat: q!(Vars { Path: path, fields }, { Path { fields } }).parse(), guard: None, fat_arrow_token: def_site(), body: Box::new(Expr::Block(ExprBlock { @@ -340,7 +371,64 @@ fn method_name(v: &Type) -> Ident { Type::Macro(_) => unimplemented!("type: macro"), Type::Never(_) => unreachable!("never type"), Type::Paren(ty) => return method_name(&ty.elem), - Type::Path(p) => p.path.segments.last().unwrap().ident.new_ident_with(handle), + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + let ident = last.ident.new_ident_with(handle); + + if last.arguments.is_empty() { + return ident; + } + + if last.ident == "Box" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(ty) => return method_name(ty), + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Box() -> T or Box without a type parameter"), + } + } + + if last.ident == "Option" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(ty) => { + let i = method_name(ty); + return i.new_ident_with(|v| v.replace("visit_", "visit_opt_")); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Box() -> T or Box without a type parameter"), + } + } + + if last.ident == "Vec" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(ty) => { + let i = method_name(ty); + return i.new_ident_with(|v| format!("{}s", v)); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Vec() -> Ret or Vec without a type parameter"), + } + } + + return ident; + } Type::Ptr(_) => unimplemented!("type: pointer"), Type::Reference(ty) => { return method_name(&ty.elem); diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index 4284b697f24d..40e01cbdec25 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,6 +1,7 @@ use std::any::Any; use swc_common::AstNode; -use swc_ecma_visit_macros::{define, visit}; +use swc_ecma_ast::*; +use swc_ecma_visit_macros::define; /// Visitable nodes. pub trait Node: Any {} @@ -25,39 +26,6 @@ define!({ pub implements: Vec, } -}); - -mod types { - use crate::{ - expr::Expr, - function::{Function, PatOrTsParamProp}, - ident::PrivateName, - prop::PropName, - stmt::BlockStmt, - typescript::{ - Accessibility, TsExprWithTypeArgs, TsIndexSignature, TsTypeAnn, TsTypeParamDecl, - TsTypeParamInstantiation, - }, - }; - use serde::{Deserialize, Serialize}; - - pub struct Class { - pub span: Span, - - pub decorators: Vec, - - pub body: Vec, - - pub super_class: Option>, - - pub is_abstract: bool, - - pub type_params: Option, - - pub super_type_params: Option, - - pub implements: Vec, - } pub enum ClassMember { Constructor(Constructor), @@ -67,1783 +35,1779 @@ mod types { PrivateProp(PrivateProp), TsIndexSignature(TsIndexSignature), } +}); - macro_rules! property { - ($name:ident, $ty:literal, $KEY:ty) => { - pub struct $name { - pub span: Span, - - pub key: $KEY, - - pub value: Option>, - - pub type_ann: Option, - - pub is_static: bool, - - pub decorators: Vec, - - pub computed: bool, - - pub accessibility: Option, - - pub is_abstract: bool, - - pub is_optional: bool, - - pub readonly: bool, - - pub definite: bool, - } - }; - } - - property!(ClassProp, "ClassProperty", Box); - property!(PrivateProp, "PrivateProperty", PrivateName); - - macro_rules! method { - ($name:ident, $ty:literal, $KEY:ty) => { - pub struct $name { - pub span: Span, - - pub key: $KEY, - - pub function: Function, - - pub kind: MethodKind, - - pub is_static: bool, - - pub accessibility: Option, - - pub is_abstract: bool, - - pub is_optional: bool, - } - }; - } - - method!(ClassMethod, "ClassMethod", PropName); - method!(PrivateMethod, "PrivateMethod", PrivateName); - - pub struct Constructor { - pub span: Span, - - pub key: PropName, - - pub params: Vec, - - pub body: Option, - - pub accessibility: Option, - - pub is_optional: bool, - } - - pub struct Decorator { - pub span: Span, - - pub expr: Box, - } - - pub enum MethodKind { - Method, - Getter, - Setter, - } - use crate::{ - class::Class, - expr::Expr, - function::Function, - ident::Ident, - pat::Pat, - typescript::{TsEnumDecl, TsInterfaceDecl, TsModuleDecl, TsTypeAliasDecl}, - }; - use string_enum::StringEnum; - use swc_common::{ast_node, Fold, Span}; - - pub enum Decl { - Class(ClassDecl), - Fn(FnDecl), - Var(VarDecl), - TsInterface(TsInterfaceDecl), - TsTypeAlias(TsTypeAliasDecl), - TsEnum(TsEnumDecl), - TsModule(TsModuleDecl), - } - - pub struct FnDecl { - pub ident: Ident, - - pub declare: bool, - - pub function: Function, - } - - pub struct ClassDecl { - pub ident: Ident, - - pub declare: bool, - - pub class: Class, - } - - pub struct VarDecl { - pub span: Span, - - pub kind: VarDeclKind, - - pub declare: bool, - - pub decls: Vec, - } - - pub enum VarDeclKind { - Var, - Let, - Const, - } - - pub struct VarDeclarator { - pub span: Span, - pub name: Pat, - - pub init: Option>, - - pub definite: bool, - } - - pub enum Expr { - This(ThisExpr), - - Array(ArrayLit), - - Object(ObjectLit), - - Fn(FnExpr), - - Unary(UnaryExpr), - - Update(UpdateExpr), - - Bin(BinExpr), - - Assign(AssignExpr), - - Member(MemberExpr), - - Cond(CondExpr), - - Call(CallExpr), - - New(NewExpr), - - Seq(SeqExpr), - - Ident(Ident), - - Lit(Lit), - - Tpl(Tpl), - - TaggedTpl(TaggedTpl), - - Arrow(ArrowExpr), - - Class(ClassExpr), - - Yield(YieldExpr), - - MetaProp(MetaPropExpr), - - Await(AwaitExpr), - - Paren(ParenExpr), - - JSXMember(JSXMemberExpr), - - JSXNamespacedName(JSXNamespacedName), - - JSXEmpty(JSXEmptyExpr), - - JSXElement(Box), - - JSXFragment(JSXFragment), - - TsTypeAssertion(TsTypeAssertion), - - TsConstAssertion(TsConstAssertion), - - TsNonNull(TsNonNullExpr), - - TsTypeCast(TsTypeCastExpr), - - TsAs(TsAsExpr), - - PrivateName(PrivateName), - - OptChain(OptChainExpr), - - Invalid(Invalid), - } - - pub struct ThisExpr { - pub span: Span, - } - - pub struct ArrayLit { - pub span: Span, - - pub elems: Vec>, - } - - pub struct ObjectLit { - pub span: Span, - - pub props: Vec, - } - - pub enum PropOrSpread { - Spread(SpreadElement), - - Prop(Box), - } - - pub struct SpreadElement { - pub dot3_token: Span, - - pub expr: Box, - } - - pub struct UnaryExpr { - pub span: Span, - - pub op: UnaryOp, - - pub arg: Box, - } - - pub struct UpdateExpr { - pub span: Span, - - pub op: UpdateOp, - - pub prefix: bool, - - pub arg: Box, - } - - pub struct BinExpr { - pub span: Span, - - pub op: BinaryOp, - - pub left: Box, - - pub right: Box, - } - - pub struct FnExpr { - pub ident: Option, - - pub function: Function, - } - - pub struct ClassExpr { - pub ident: Option, - - pub class: Class, - } - - pub struct AssignExpr { - pub span: Span, - - pub op: AssignOp, - - pub left: PatOrExpr, - - pub right: Box, - } - - pub struct MemberExpr { - pub span: Span, - - pub obj: ExprOrSuper, - - pub prop: Box, - - pub computed: bool, - } - - pub struct CondExpr { - pub span: Span, - - pub test: Box, - - pub cons: Box, - - pub alt: Box, - } - - pub struct CallExpr { - pub span: Span, - - pub callee: ExprOrSuper, - - pub args: Vec, - - pub type_args: Option, - } - - pub struct NewExpr { - pub span: Span, - - pub callee: Box, - - pub args: Option>, - - pub type_args: Option, - } - - pub struct SeqExpr { - pub span: Span, - - pub exprs: Vec>, - } - - pub struct ArrowExpr { - pub span: Span, - - pub params: Vec, - - pub body: BlockStmtOrExpr, - - pub is_async: bool, - - pub is_generator: bool, - - pub type_params: Option, - - pub return_type: Option, - } - - pub struct YieldExpr { - pub span: Span, - - pub arg: Option>, - - pub delegate: bool, - } - - pub struct MetaPropExpr { - pub meta: Ident, - - pub prop: Ident, - } - - pub struct AwaitExpr { - pub span: Span, - - pub arg: Box, - } - - pub struct Tpl { - pub span: Span, - - pub exprs: Vec>, - - pub quasis: Vec, - } - - pub struct TaggedTpl { - pub span: Span, - - pub tag: Box, - - pub exprs: Vec>, - pub quasis: Vec, - - pub type_params: Option, - } - - pub struct TplElement { - pub span: Span, - pub tail: bool, - pub cooked: Option, - pub raw: Str, - } - - pub struct ParenExpr { - pub span: Span, - - pub expr: Box, - } - - pub enum ExprOrSuper { - Super(Super), - - Expr(Box), - } - - pub struct Super { - pub span: Span, - } - - pub struct ExprOrSpread { - pub spread: Option, - - pub expr: Box, - } - - pub enum BlockStmtOrExpr { - BlockStmt(BlockStmt), - Expr(Box), - } - - pub enum PatOrExpr { - Expr(Box), - Pat(Box), - } - - pub struct OptChainExpr { - pub span: Span, - pub expr: Box, - } - - pub struct Function { - pub params: Vec, - - pub decorators: Vec, - - pub span: Span, - - pub body: Option, - - pub is_generator: bool, - - pub is_async: bool, - - pub type_params: Option, - - pub return_type: Option, - } - - pub enum PatOrTsParamProp { - TsParamProp(TsParamProp), - Pat(Pat), - } - - pub struct Ident { - pub span: Span, - pub sym: JsWord, - pub type_ann: Option, - pub optional: bool, - } - - pub struct PrivateName { - pub span: Span, - pub id: Ident, - } - - pub enum JSXObject { - JSXMemberExpr(Box), - Ident(Ident), - } - - pub struct JSXMemberExpr { - pub obj: JSXObject, - - pub prop: Ident, - } - - pub struct JSXNamespacedName { - pub ns: Ident, - pub name: Ident, - } - - pub struct JSXEmptyExpr { - pub span: Span, - } - - pub struct JSXExprContainer { - pub span: Span, - pub expr: JSXExpr, - } - - pub enum JSXExpr { - JSXEmptyExpr(JSXEmptyExpr), - Expr(Box), - } - - pub struct JSXSpreadChild { - pub span: Span, - pub expr: Box, - } - - pub enum JSXElementName { - Ident(Ident), - JSXMemberExpr(JSXMemberExpr), - JSXNamespacedName(JSXNamespacedName), - } - - pub struct JSXOpeningElement { - pub name: JSXElementName, - - pub span: Span, - - pub attrs: Vec, - - pub self_closing: bool, - - pub type_args: Option, - } - - pub enum JSXAttrOrSpread { - JSXAttr(JSXAttr), - SpreadElement(SpreadElement), - } - - pub struct JSXClosingElement { - pub span: Span, - pub name: JSXElementName, - } - - pub struct JSXAttr { - pub span: Span, - pub name: JSXAttrName, - pub value: Option, - } - - pub enum JSXAttrName { - Ident(Ident), - JSXNamespacedName(JSXNamespacedName), - } - - pub enum JSXAttrValue { - Lit(Lit), - - JSXExprContainer(JSXExprContainer), - - JSXElement(Box), - - JSXFragment(JSXFragment), - } - - pub struct JSXText { - pub span: Span, - pub value: JsWord, - pub raw: JsWord, - } - - pub struct JSXElement { - pub span: Span, - pub opening: JSXOpeningElement, - pub children: Vec, - pub closing: Option, - } - - pub enum JSXElementChild { - JSXText(JSXText), - - JSXExprContainer(JSXExprContainer), - - JSXSpreadChild(JSXSpreadChild), - - JSXElement(Box), - - JSXFragment(JSXFragment), - } - - pub struct JSXFragment { - pub span: Span, - - pub opening: JSXOpeningFragment, - - pub children: Vec, - - pub closing: JSXClosingFragment, - } - - pub struct JSXOpeningFragment { - pub span: Span, - } - - pub struct JSXClosingFragment { - pub span: Span, - } - - pub struct Invalid { - pub span: Span, - } - - pub enum Lit { - Str(Str), - - Bool(Bool), - - Null(Null), - - Num(Number), - - BigInt(BigInt), - - Regex(Regex), - - JSXText(JSXText), - } - - pub struct BigInt { - pub span: Span, - pub value: BigIntValue, - } - - pub struct Str { - pub span: Span, - - pub value: JsWord, - - pub has_escape: bool, - } - - pub struct Bool { - pub span: Span, - pub value: bool, - } - - pub struct Null { - pub span: Span, - } - - pub struct Regex { - pub span: Span, - - pub exp: JsWord, - - pub flags: JsWord, - } - - pub struct Number { - pub span: Span, - pub value: f64, - } - - pub enum Program { - Module(Module), - Script(Script), - } - - pub struct Module { - pub span: Span, - - pub body: Vec, - - pub shebang: Option, - } - - pub struct Script { - pub span: Span, - - pub body: Vec, - - pub shebang: Option, - } - - pub enum ModuleItem { - ModuleDecl(ModuleDecl), - Stmt(Stmt), - } - - pub enum ModuleDecl { - Import(ImportDecl), - - ExportDecl(ExportDecl), - - ExportNamed(NamedExport), - - ExportDefaultDecl(ExportDefaultDecl), - - ExportDefaultExpr(ExportDefaultExpr), - - ExportAll(ExportAll), - - TsImportEquals(TsImportEqualsDecl), - - TsExportAssignment(TsExportAssignment), - - TsNamespaceExport(TsNamespaceExportDecl), - } - - pub struct ExportDefaultExpr { - pub span: Span, - - pub expr: Box, - } - - pub struct ExportDecl { - pub span: Span, - - pub decl: Decl, - } - - pub struct ImportDecl { - pub span: Span, - - pub specifiers: Vec, - - pub src: Str, - - pub type_only: bool, - } - - pub struct ExportAll { - pub span: Span, - - pub src: Str, - } - - pub struct NamedExport { - pub span: Span, - - pub specifiers: Vec, - - pub src: Option, - - pub type_only: bool, - } - - pub struct ExportDefaultDecl { - pub span: Span, - - pub decl: DefaultDecl, - } - - pub enum DefaultDecl { - Class(ClassExpr), - - Fn(FnExpr), - - TsInterfaceDecl(TsInterfaceDecl), - } - - pub enum ImportSpecifier { - Specific(ImportSpecific), - Default(ImportDefault), - Namespace(ImportStarAs), - } - - pub struct ImportDefault { - pub span: Span, - - pub local: Ident, - } - pub struct ImportStarAs { - pub span: Span, - - pub local: Ident, - } - pub struct ImportSpecific { - pub span: Span, - - pub local: Ident, - - pub imported: Option, - } - - pub enum ExportSpecifier { - Namespace(NamespaceExportSpecifier), - - Default(DefaultExportSpecifier), - - Named(NamedExportSpecifier), - } - - pub struct NamespaceExportSpecifier { - pub span: Span, - - pub name: Ident, - } - - pub struct DefaultExportSpecifier { - pub exported: Ident, - } - - pub struct NamedExportSpecifier { - pub span: Span, - pub orig: Ident, - pub exported: Option, - } - - pub enum BinaryOp { - EqEq, - NotEq, - EqEqEq, - NotEqEq, - Lt, - LtEq, - Gt, - GtEq, - LShift, - RShift, - ZeroFillRShift, - - Add, - Sub, - Mul, - Div, - Mod, - - BitOr, - BitXor, - BitAnd, - - LogicalOr, - - LogicalAnd, - - In, - InstanceOf, - - Exp, - - NullishCoalescing, - } - - pub enum AssignOp { - Assign, - AddAssign, - SubAssign, - MulAssign, - DivAssign, - ModAssign, - LShiftAssign, - RShiftAssign, - ZeroFillRShiftAssign, - BitOrAssign, - BitXorAssign, - BitAndAssign, - - ExpAssign, - } - - pub enum UpdateOp { - PlusPlus, - MinusMinus, - } - - pub enum UnaryOp { - Minus, - Plus, - Bang, - Tilde, - TypeOf, - Void, - Delete, - } - - pub enum Pat { - Ident(Ident), - - Array(ArrayPat), - - Rest(RestPat), - - Object(ObjectPat), - - Assign(AssignPat), - - Invalid(Invalid), - - Expr(Box), - } - - pub struct ArrayPat { - pub span: Span, - - pub elems: Vec>, - - pub optional: bool, - - pub type_ann: Option, - } - - pub struct ObjectPat { - pub span: Span, - - pub props: Vec, - - pub optional: bool, - - pub type_ann: Option, - } - - pub struct AssignPat { - pub span: Span, - - pub left: Box, - - pub right: Box, - - pub type_ann: Option, - } - - pub struct RestPat { - pub span: Span, - - pub dot3_token: Span, - - pub arg: Box, - - pub type_ann: Option, - } - - pub enum ObjectPatProp { - KeyValue(KeyValuePatProp), - - Assign(AssignPatProp), - - Rest(RestPat), - } - - pub struct KeyValuePatProp { - pub key: PropName, - - pub value: Box, - } - pub struct AssignPatProp { - pub span: Span, - pub key: Ident, - - pub value: Option>, - } - - pub enum Prop { - Shorthand(Ident), - - KeyValue(KeyValueProp), - - Assign(AssignProp), - - Getter(GetterProp), - - Setter(SetterProp), - - Method(MethodProp), - } - - pub struct KeyValueProp { - pub key: PropName, - - pub value: Box, - } - - pub struct AssignProp { - pub key: Ident, - pub value: Box, - } - - pub struct GetterProp { - pub span: Span, - pub key: PropName, - pub type_ann: Option, - pub body: Option, - } - pub struct SetterProp { - pub span: Span, - pub key: PropName, - pub param: Pat, - pub body: Option, - } - pub struct MethodProp { - pub key: PropName, - - pub function: Function, - } - - pub enum PropName { - Ident(Ident), - Str(Str), - Num(Number), - Computed(ComputedPropName), - } - - pub struct ComputedPropName { - pub span: Span, - pub expr: Box, - } - use crate::{ - decl::{Decl, VarDecl}, - expr::Expr, - ident::Ident, - pat::Pat, - }; - - pub struct BlockStmt { - pub span: Span, - - pub stmts: Vec, - } - - pub enum Stmt { - Block(BlockStmt), - - Empty(EmptyStmt), - - Debugger(DebuggerStmt), - - With(WithStmt), - - Return(ReturnStmt), - - Labeled(LabeledStmt), - - Break(BreakStmt), - - Continue(ContinueStmt), - - If(IfStmt), - - Switch(SwitchStmt), - - Throw(ThrowStmt), - - Try(TryStmt), - - While(WhileStmt), - - DoWhile(DoWhileStmt), - - For(ForStmt), - - ForIn(ForInStmt), - - ForOf(ForOfStmt), - - Decl(Decl), - - Expr(ExprStmt), - } - - pub struct ExprStmt { - pub span: Span, - pub expr: Box, - } - - pub struct EmptyStmt { - pub span: Span, - } - - pub struct DebuggerStmt { - pub span: Span, - } - - pub struct WithStmt { - pub span: Span, - pub obj: Box, - pub body: Box, - } - - pub struct ReturnStmt { - pub span: Span, - pub arg: Option>, - } - - pub struct LabeledStmt { - pub span: Span, - pub label: Ident, - pub body: Box, - } - - pub struct BreakStmt { - pub span: Span, - pub label: Option, - } - - pub struct ContinueStmt { - pub span: Span, - pub label: Option, - } - - pub struct IfStmt { - pub span: Span, - pub test: Box, - - pub cons: Box, - - pub alt: Option>, - } - - pub struct SwitchStmt { - pub span: Span, - pub discriminant: Box, - pub cases: Vec, - } - - pub struct ThrowStmt { - pub span: Span, - pub arg: Box, - } - - pub struct TryStmt { - pub span: Span, - - pub block: BlockStmt, - - pub handler: Option, - - pub finalizer: Option, - } - - pub struct WhileStmt { - pub span: Span, - pub test: Box, - pub body: Box, - } - - pub struct DoWhileStmt { - pub span: Span, - pub test: Box, - pub body: Box, - } - - pub struct ForStmt { - pub span: Span, - - pub init: Option, - - pub test: Option>, - - pub update: Option>, - - pub body: Box, - } - - pub struct ForInStmt { - pub span: Span, - pub left: VarDeclOrPat, - pub right: Box, - pub body: Box, - } - - pub struct ForOfStmt { - pub span: Span, - pub await_token: Option, - pub left: VarDeclOrPat, - pub right: Box, - pub body: Box, - } - - pub struct SwitchCase { - pub span: Span, - - pub test: Option>, - - pub cons: Vec, - } - - pub struct CatchClause { - pub span: Span, - pub param: Option, - - pub body: BlockStmt, - } - - pub enum VarDeclOrPat { - VarDecl(VarDecl), - - Pat(Pat), - } - - pub enum VarDeclOrExpr { - VarDecl(VarDecl), - - Expr(Box), - } - - pub struct TsTypeAnn { - pub span: Span, - pub type_ann: Box, - } - - pub struct TsTypeParamDecl { - pub span: Span, - pub params: Vec, - } - - pub struct TsTypeParam { - pub span: Span, - pub name: Ident, - - pub constraint: Option>, - - pub default: Option>, - } - - pub struct TsTypeParamInstantiation { - pub span: Span, - pub params: Vec>, - } - - pub struct TsTypeCastExpr { - pub span: Span, - pub expr: Box, - pub type_ann: TsTypeAnn, - } - - pub struct TsParamProp { - pub span: Span, - pub decorators: Vec, - pub accessibility: Option, - pub readonly: bool, - pub param: TsParamPropParam, - } - - pub enum TsParamPropParam { - Ident(Ident), - - Assign(AssignPat), - } - - pub struct TsQualifiedName { - pub left: TsEntityName, - pub right: Ident, - } - - pub enum TsEntityName { - TsQualifiedName(Box), - - Ident(Ident), - } - - pub enum TsSignatureDecl { - TsCallSignatureDecl(TsCallSignatureDecl), - - TsConstructSignatureDecl(TsConstructSignatureDecl), - - TsMethodSignature(TsMethodSignature), - - TsFnType(TsFnType), - - TsConstructorType(TsConstructorType), - } - - pub enum TsTypeElement { - TsCallSignatureDecl(TsCallSignatureDecl), - - TsConstructSignatureDecl(TsConstructSignatureDecl), - - TsPropertySignature(TsPropertySignature), - - TsMethodSignature(TsMethodSignature), - - TsIndexSignature(TsIndexSignature), - } - - pub struct TsCallSignatureDecl { - pub span: Span, - pub params: Vec, - pub type_ann: Option, - pub type_params: Option, - } - - pub struct TsConstructSignatureDecl { - pub span: Span, - pub params: Vec, - pub type_ann: Option, - pub type_params: Option, - } - - pub struct TsPropertySignature { - pub span: Span, - pub readonly: bool, - pub key: Box, - pub computed: bool, - pub optional: bool, - pub init: Option>, - pub params: Vec, - pub type_ann: Option, - pub type_params: Option, - } - - pub struct TsMethodSignature { - pub span: Span, - pub readonly: bool, - pub key: Box, - pub computed: bool, - pub optional: bool, - pub params: Vec, - pub type_ann: Option, - pub type_params: Option, - } - - pub struct TsIndexSignature { - pub params: Vec, - pub type_ann: Option, - - pub readonly: bool, - pub span: Span, - } - - pub enum TsType { - TsKeywordType(TsKeywordType), - - TsThisType(TsThisType), - - TsFnOrConstructorType(TsFnOrConstructorType), - - TsTypeRef(TsTypeRef), - - TsTypeQuery(TsTypeQuery), - - TsTypeLit(TsTypeLit), - - TsArrayType(TsArrayType), - - TsTupleType(TsTupleType), - - TsOptionalType(TsOptionalType), - - TsRestType(TsRestType), - - TsUnionOrIntersectionType(TsUnionOrIntersectionType), - - TsConditionalType(TsConditionalType), - - TsInferType(TsInferType), - - TsParenthesizedType(TsParenthesizedType), - - TsTypeOperator(TsTypeOperator), - - TsIndexedAccessType(TsIndexedAccessType), - - TsMappedType(TsMappedType), - - TsLitType(TsLitType), - - TsTypePredicate(TsTypePredicate), - - TsImportType(TsImportType), - } - - pub enum TsFnOrConstructorType { - TsFnType(TsFnType), - TsConstructorType(TsConstructorType), - } - - impl From for TsType { - fn from(t: TsFnType) -> Self { - TsFnOrConstructorType::TsFnType(t).into() - } - } - - impl From for TsType { - fn from(t: TsConstructorType) -> Self { - TsFnOrConstructorType::TsConstructorType(t).into() - } - } - - impl From for TsType { - fn from(t: TsUnionType) -> Self { - TsUnionOrIntersectionType::TsUnionType(t).into() - } - } - - impl From for TsType { - fn from(t: TsIntersectionType) -> Self { - TsUnionOrIntersectionType::TsIntersectionType(t).into() - } - } - - pub struct TsKeywordType { - pub span: Span, - pub kind: TsKeywordTypeKind, - } - - pub enum TsKeywordTypeKind { - TsAnyKeyword, - - TsUnknownKeyword, - - TsNumberKeyword, - - TsObjectKeyword, - - TsBooleanKeyword, - - TsBigIntKeyword, - - TsStringKeyword, - - TsSymbolKeyword, - - TsVoidKeyword, - - TsUndefinedKeyword, - - TsNullKeyword, - - TsNeverKeyword, - } - - pub struct TsThisType { - pub span: Span, - } - - pub enum TsFnParam { - Ident(Ident), - - Array(ArrayPat), - - Rest(RestPat), - - Object(ObjectPat), - } - - pub struct TsFnType { - pub span: Span, - pub params: Vec, - - pub type_params: Option, - pub type_ann: TsTypeAnn, - } - - pub struct TsConstructorType { - pub span: Span, - pub params: Vec, - pub type_params: Option, - pub type_ann: TsTypeAnn, - } - - pub struct TsTypeRef { - pub span: Span, - pub type_name: TsEntityName, - pub type_params: Option, - } - - pub struct TsTypePredicate { - pub span: Span, - pub asserts: bool, - pub param_name: TsThisTypeOrIdent, - pub type_ann: Option, - } - - pub enum TsThisTypeOrIdent { - TsThisType(TsThisType), - - Ident(Ident), - } - - pub struct TsTypeQuery { - pub span: Span, - pub expr_name: TsTypeQueryExpr, - } - - pub enum TsTypeQueryExpr { - TsEntityName(TsEntityName), - Import(TsImportType), - } - - pub struct TsImportType { - pub span: Span, - pub arg: Str, - pub qualifier: Option, - pub type_args: Option, - } - - pub struct TsTypeLit { - pub span: Span, - pub members: Vec, - } - - pub struct TsArrayType { - pub span: Span, - pub elem_type: Box, - } - - pub struct TsTupleType { - pub span: Span, - pub elem_types: Vec>, - } - - pub struct TsOptionalType { - pub span: Span, - pub type_ann: Box, - } - - pub struct TsRestType { - pub span: Span, - pub type_ann: Box, - } - - pub enum TsUnionOrIntersectionType { - TsUnionType(TsUnionType), - - TsIntersectionType(TsIntersectionType), - } - - pub struct TsUnionType { - pub span: Span, - pub types: Vec>, - } - - pub struct TsIntersectionType { - pub span: Span, - pub types: Vec>, - } - - pub struct TsConditionalType { - pub span: Span, - pub check_type: Box, - pub extends_type: Box, - pub true_type: Box, - pub false_type: Box, - } - - pub struct TsInferType { - pub span: Span, - pub type_param: TsTypeParam, - } - - pub struct TsParenthesizedType { - pub span: Span, - pub type_ann: Box, - } - - pub struct TsTypeOperator { - pub span: Span, - pub op: TsTypeOperatorOp, - pub type_ann: Box, - } - - pub enum TsTypeOperatorOp { - KeyOf, - Unique, - ReadOnly, - } - - pub struct TsIndexedAccessType { - pub span: Span, - pub readonly: bool, - pub obj_type: Box, - pub index_type: Box, - } - - pub enum TruePlusMinus { - True, - Plus, - Minus, - } - - impl Serialize for TruePlusMinus { - fn serialize(&self, serializer: S) -> Result - where - S: ::serde::Serializer, - { - match *self { - TruePlusMinus::True => serializer.serialize_bool(true), - TruePlusMinus::Plus => serializer.serialize_str("+"), - TruePlusMinus::Minus => serializer.serialize_str("-"), - } - } - } - - impl<'de> Deserialize<'de> for TruePlusMinus { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct TruePlusMinusVisitor; - - impl<'de> Visitor<'de> for TruePlusMinusVisitor { - type Value = TruePlusMinus; - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("one of '+', '-', true") - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - match value { - "+" => Ok(TruePlusMinus::Plus), - "-" => Ok(TruePlusMinus::Minus), - "true" => Ok(TruePlusMinus::True), - _ => Err(de::Error::invalid_value(Unexpected::Str(value), &self)), - } - } - - fn visit_bool(self, value: bool) -> Result - where - E: de::Error, - { - if value { - Ok(TruePlusMinus::True) - } else { - Err(de::Error::invalid_value(Unexpected::Bool(value), &self)) - } - } - } - - deserializer.deserialize_any(TruePlusMinusVisitor) - } - } - - pub struct TsMappedType { - pub span: Span, - pub readonly: Option, - pub type_param: TsTypeParam, - pub optional: Option, - pub type_ann: Option>, - } - - pub struct TsLitType { - pub span: Span, - pub lit: TsLit, - } - - pub enum TsLit { - Number(Number), - - Str(Str), - - Bool(Bool), - } - - pub struct TsInterfaceDecl { - pub span: Span, - pub id: Ident, - pub declare: bool, - pub type_params: Option, - pub extends: Vec, - pub body: TsInterfaceBody, - } - - pub struct TsInterfaceBody { - pub span: Span, - pub body: Vec, - } - - pub struct TsExprWithTypeArgs { - pub span: Span, - pub expr: TsEntityName, - pub type_args: Option, - } - - pub struct TsTypeAliasDecl { - pub span: Span, - pub declare: bool, - pub id: Ident, - pub type_params: Option, - pub type_ann: Box, - } - - pub struct TsEnumDecl { - pub span: Span, - pub declare: bool, - pub is_const: bool, - pub id: Ident, - pub members: Vec, - } - - pub struct TsEnumMember { - pub span: Span, - pub id: TsEnumMemberId, - pub init: Option>, - } - - pub enum TsEnumMemberId { - Ident(Ident), - - Str(Str), - } - - pub struct TsModuleDecl { - pub span: Span, - pub declare: bool, - pub global: bool, - pub id: TsModuleName, - pub body: Option, - } - - pub enum TsNamespaceBody { - TsModuleBlock(TsModuleBlock), - - TsNamespaceDecl(TsNamespaceDecl), - } - - pub struct TsModuleBlock { - pub span: Span, - pub body: Vec, - } - - pub struct TsNamespaceDecl { - pub span: Span, - pub declare: bool, - pub global: bool, - pub id: Ident, - pub body: Box, - } - - pub enum TsModuleName { - Ident(Ident), - - Str(Str), - } - - pub struct TsImportEqualsDecl { - pub span: Span, - pub declare: bool, - pub is_export: bool, - pub id: Ident, - pub module_ref: TsModuleRef, - } - - pub enum TsModuleRef { - TsEntityName(TsEntityName), - - TsExternalModuleRef(TsExternalModuleRef), - } - - pub struct TsExternalModuleRef { - pub span: Span, - pub expr: Str, - } - - pub struct TsExportAssignment { - pub span: Span, - pub expr: Box, - } - - pub struct TsNamespaceExportDecl { - pub span: Span, - pub id: Ident, - } - - pub struct TsAsExpr { - pub span: Span, - pub expr: Box, - pub type_ann: Box, - } - - pub struct TsTypeAssertion { - pub span: Span, - pub expr: Box, - pub type_ann: Box, - } - - pub struct TsNonNullExpr { - pub span: Span, - pub expr: Box, - } - - pub enum Accessibility { - Public, - Protected, - Private, - } - - pub struct TsConstAssertion { - pub span: Span, - pub expr: Box, - } -} +// mod types { +// +// + +// +// macro_rules! property { +// ($name:ident, $ty:literal, $KEY:ty) => { +// pub struct $name { +// pub span: Span, +// +// pub key: $KEY, +// +// pub value: Option>, +// +// pub type_ann: Option, +// +// pub is_static: bool, +// +// pub decorators: Vec, +// +// pub computed: bool, +// +// pub accessibility: Option, +// +// pub is_abstract: bool, +// +// pub is_optional: bool, +// +// pub readonly: bool, +// +// pub definite: bool, +// } +// }; +// } +// +// property!(ClassProp, "ClassProperty", Box); +// property!(PrivateProp, "PrivateProperty", PrivateName); +// +// macro_rules! method { +// ($name:ident, $ty:literal, $KEY:ty) => { +// pub struct $name { +// pub span: Span, +// +// pub key: $KEY, +// +// pub function: Function, +// +// pub kind: MethodKind, +// +// pub is_static: bool, +// +// pub accessibility: Option, +// +// pub is_abstract: bool, +// +// pub is_optional: bool, +// } +// }; +// } +// +// method!(ClassMethod, "ClassMethod", PropName); +// method!(PrivateMethod, "PrivateMethod", PrivateName); +// +// pub struct Constructor { +// pub span: Span, +// +// pub key: PropName, +// +// pub params: Vec, +// +// pub body: Option, +// +// pub accessibility: Option, +// +// pub is_optional: bool, +// } +// +// pub struct Decorator { +// pub span: Span, +// +// pub expr: Box, +// } +// +// pub enum MethodKind { +// Method, +// Getter, +// Setter, +// } +// +// pub enum Decl { +// Class(ClassDecl), +// Fn(FnDecl), +// Var(VarDecl), +// TsInterface(TsInterfaceDecl), +// TsTypeAlias(TsTypeAliasDecl), +// TsEnum(TsEnumDecl), +// TsModule(TsModuleDecl), +// } +// +// pub struct FnDecl { +// pub ident: Ident, +// +// pub declare: bool, +// +// pub function: Function, +// } +// +// pub struct ClassDecl { +// pub ident: Ident, +// +// pub declare: bool, +// +// pub class: Class, +// } +// +// pub struct VarDecl { +// pub span: Span, +// +// pub kind: VarDeclKind, +// +// pub declare: bool, +// +// pub decls: Vec, +// } +// +// pub enum VarDeclKind { +// Var, +// Let, +// Const, +// } +// +// pub struct VarDeclarator { +// pub span: Span, +// pub name: Pat, +// +// pub init: Option>, +// +// pub definite: bool, +// } +// +// pub enum Expr { +// This(ThisExpr), +// +// Array(ArrayLit), +// +// Object(ObjectLit), +// +// Fn(FnExpr), +// +// Unary(UnaryExpr), +// +// Update(UpdateExpr), +// +// Bin(BinExpr), +// +// Assign(AssignExpr), +// +// Member(MemberExpr), +// +// Cond(CondExpr), +// +// Call(CallExpr), +// +// New(NewExpr), +// +// Seq(SeqExpr), +// +// Ident(Ident), +// +// Lit(Lit), +// +// Tpl(Tpl), +// +// TaggedTpl(TaggedTpl), +// +// Arrow(ArrowExpr), +// +// Class(ClassExpr), +// +// Yield(YieldExpr), +// +// MetaProp(MetaPropExpr), +// +// Await(AwaitExpr), +// +// Paren(ParenExpr), +// +// JSXMember(JSXMemberExpr), +// +// JSXNamespacedName(JSXNamespacedName), +// +// JSXEmpty(JSXEmptyExpr), +// +// JSXElement(Box), +// +// JSXFragment(JSXFragment), +// +// TsTypeAssertion(TsTypeAssertion), +// +// TsConstAssertion(TsConstAssertion), +// +// TsNonNull(TsNonNullExpr), +// +// TsTypeCast(TsTypeCastExpr), +// +// TsAs(TsAsExpr), +// +// PrivateName(PrivateName), +// +// OptChain(OptChainExpr), +// +// Invalid(Invalid), +// } +// +// pub struct ThisExpr { +// pub span: Span, +// } +// +// pub struct ArrayLit { +// pub span: Span, +// +// pub elems: Vec>, +// } +// +// pub struct ObjectLit { +// pub span: Span, +// +// pub props: Vec, +// } +// +// pub enum PropOrSpread { +// Spread(SpreadElement), +// +// Prop(Box), +// } +// +// pub struct SpreadElement { +// pub dot3_token: Span, +// +// pub expr: Box, +// } +// +// pub struct UnaryExpr { +// pub span: Span, +// +// pub op: UnaryOp, +// +// pub arg: Box, +// } +// +// pub struct UpdateExpr { +// pub span: Span, +// +// pub op: UpdateOp, +// +// pub prefix: bool, +// +// pub arg: Box, +// } +// +// pub struct BinExpr { +// pub span: Span, +// +// pub op: BinaryOp, +// +// pub left: Box, +// +// pub right: Box, +// } +// +// pub struct FnExpr { +// pub ident: Option, +// +// pub function: Function, +// } +// +// pub struct ClassExpr { +// pub ident: Option, +// +// pub class: Class, +// } +// +// pub struct AssignExpr { +// pub span: Span, +// +// pub op: AssignOp, +// +// pub left: PatOrExpr, +// +// pub right: Box, +// } +// +// pub struct MemberExpr { +// pub span: Span, +// +// pub obj: ExprOrSuper, +// +// pub prop: Box, +// +// pub computed: bool, +// } +// +// pub struct CondExpr { +// pub span: Span, +// +// pub test: Box, +// +// pub cons: Box, +// +// pub alt: Box, +// } +// +// pub struct CallExpr { +// pub span: Span, +// +// pub callee: ExprOrSuper, +// +// pub args: Vec, +// +// pub type_args: Option, +// } +// +// pub struct NewExpr { +// pub span: Span, +// +// pub callee: Box, +// +// pub args: Option>, +// +// pub type_args: Option, +// } +// +// pub struct SeqExpr { +// pub span: Span, +// +// pub exprs: Vec>, +// } +// +// pub struct ArrowExpr { +// pub span: Span, +// +// pub params: Vec, +// +// pub body: BlockStmtOrExpr, +// +// pub is_async: bool, +// +// pub is_generator: bool, +// +// pub type_params: Option, +// +// pub return_type: Option, +// } +// +// pub struct YieldExpr { +// pub span: Span, +// +// pub arg: Option>, +// +// pub delegate: bool, +// } +// +// pub struct MetaPropExpr { +// pub meta: Ident, +// +// pub prop: Ident, +// } +// +// pub struct AwaitExpr { +// pub span: Span, +// +// pub arg: Box, +// } +// +// pub struct Tpl { +// pub span: Span, +// +// pub exprs: Vec>, +// +// pub quasis: Vec, +// } +// +// pub struct TaggedTpl { +// pub span: Span, +// +// pub tag: Box, +// +// pub exprs: Vec>, +// pub quasis: Vec, +// +// pub type_params: Option, +// } +// +// pub struct TplElement { +// pub span: Span, +// pub tail: bool, +// pub cooked: Option, +// pub raw: Str, +// } +// +// pub struct ParenExpr { +// pub span: Span, +// +// pub expr: Box, +// } +// +// pub enum ExprOrSuper { +// Super(Super), +// +// Expr(Box), +// } +// +// pub struct Super { +// pub span: Span, +// } +// +// pub struct ExprOrSpread { +// pub spread: Option, +// +// pub expr: Box, +// } +// +// pub enum BlockStmtOrExpr { +// BlockStmt(BlockStmt), +// Expr(Box), +// } +// +// pub enum PatOrExpr { +// Expr(Box), +// Pat(Box), +// } +// +// pub struct OptChainExpr { +// pub span: Span, +// pub expr: Box, +// } +// +// pub struct Function { +// pub params: Vec, +// +// pub decorators: Vec, +// +// pub span: Span, +// +// pub body: Option, +// +// pub is_generator: bool, +// +// pub is_async: bool, +// +// pub type_params: Option, +// +// pub return_type: Option, +// } +// +// pub enum PatOrTsParamProp { +// TsParamProp(TsParamProp), +// Pat(Pat), +// } +// +// pub struct Ident { +// pub span: Span, +// pub sym: JsWord, +// pub type_ann: Option, +// pub optional: bool, +// } +// +// pub struct PrivateName { +// pub span: Span, +// pub id: Ident, +// } +// +// pub enum JSXObject { +// JSXMemberExpr(Box), +// Ident(Ident), +// } +// +// pub struct JSXMemberExpr { +// pub obj: JSXObject, +// +// pub prop: Ident, +// } +// +// pub struct JSXNamespacedName { +// pub ns: Ident, +// pub name: Ident, +// } +// +// pub struct JSXEmptyExpr { +// pub span: Span, +// } +// +// pub struct JSXExprContainer { +// pub span: Span, +// pub expr: JSXExpr, +// } +// +// pub enum JSXExpr { +// JSXEmptyExpr(JSXEmptyExpr), +// Expr(Box), +// } +// +// pub struct JSXSpreadChild { +// pub span: Span, +// pub expr: Box, +// } +// +// pub enum JSXElementName { +// Ident(Ident), +// JSXMemberExpr(JSXMemberExpr), +// JSXNamespacedName(JSXNamespacedName), +// } +// +// pub struct JSXOpeningElement { +// pub name: JSXElementName, +// +// pub span: Span, +// +// pub attrs: Vec, +// +// pub self_closing: bool, +// +// pub type_args: Option, +// } +// +// pub enum JSXAttrOrSpread { +// JSXAttr(JSXAttr), +// SpreadElement(SpreadElement), +// } +// +// pub struct JSXClosingElement { +// pub span: Span, +// pub name: JSXElementName, +// } +// +// pub struct JSXAttr { +// pub span: Span, +// pub name: JSXAttrName, +// pub value: Option, +// } +// +// pub enum JSXAttrName { +// Ident(Ident), +// JSXNamespacedName(JSXNamespacedName), +// } +// +// pub enum JSXAttrValue { +// Lit(Lit), +// +// JSXExprContainer(JSXExprContainer), +// +// JSXElement(Box), +// +// JSXFragment(JSXFragment), +// } +// +// pub struct JSXText { +// pub span: Span, +// pub value: JsWord, +// pub raw: JsWord, +// } +// +// pub struct JSXElement { +// pub span: Span, +// pub opening: JSXOpeningElement, +// pub children: Vec, +// pub closing: Option, +// } +// +// pub enum JSXElementChild { +// JSXText(JSXText), +// +// JSXExprContainer(JSXExprContainer), +// +// JSXSpreadChild(JSXSpreadChild), +// +// JSXElement(Box), +// +// JSXFragment(JSXFragment), +// } +// +// pub struct JSXFragment { +// pub span: Span, +// +// pub opening: JSXOpeningFragment, +// +// pub children: Vec, +// +// pub closing: JSXClosingFragment, +// } +// +// pub struct JSXOpeningFragment { +// pub span: Span, +// } +// +// pub struct JSXClosingFragment { +// pub span: Span, +// } +// +// pub struct Invalid { +// pub span: Span, +// } +// +// pub enum Lit { +// Str(Str), +// +// Bool(Bool), +// +// Null(Null), +// +// Num(Number), +// +// BigInt(BigInt), +// +// Regex(Regex), +// +// JSXText(JSXText), +// } +// +// pub struct BigInt { +// pub span: Span, +// pub value: BigIntValue, +// } +// +// pub struct Str { +// pub span: Span, +// +// pub value: JsWord, +// +// pub has_escape: bool, +// } +// +// pub struct Bool { +// pub span: Span, +// pub value: bool, +// } +// +// pub struct Null { +// pub span: Span, +// } +// +// pub struct Regex { +// pub span: Span, +// +// pub exp: JsWord, +// +// pub flags: JsWord, +// } +// +// pub struct Number { +// pub span: Span, +// pub value: f64, +// } +// +// pub enum Program { +// Module(Module), +// Script(Script), +// } +// +// pub struct Module { +// pub span: Span, +// +// pub body: Vec, +// +// pub shebang: Option, +// } +// +// pub struct Script { +// pub span: Span, +// +// pub body: Vec, +// +// pub shebang: Option, +// } +// +// pub enum ModuleItem { +// ModuleDecl(ModuleDecl), +// Stmt(Stmt), +// } +// +// pub enum ModuleDecl { +// Import(ImportDecl), +// +// ExportDecl(ExportDecl), +// +// ExportNamed(NamedExport), +// +// ExportDefaultDecl(ExportDefaultDecl), +// +// ExportDefaultExpr(ExportDefaultExpr), +// +// ExportAll(ExportAll), +// +// TsImportEquals(TsImportEqualsDecl), +// +// TsExportAssignment(TsExportAssignment), +// +// TsNamespaceExport(TsNamespaceExportDecl), +// } +// +// pub struct ExportDefaultExpr { +// pub span: Span, +// +// pub expr: Box, +// } +// +// pub struct ExportDecl { +// pub span: Span, +// +// pub decl: Decl, +// } +// +// pub struct ImportDecl { +// pub span: Span, +// +// pub specifiers: Vec, +// +// pub src: Str, +// +// pub type_only: bool, +// } +// +// pub struct ExportAll { +// pub span: Span, +// +// pub src: Str, +// } +// +// pub struct NamedExport { +// pub span: Span, +// +// pub specifiers: Vec, +// +// pub src: Option, +// +// pub type_only: bool, +// } +// +// pub struct ExportDefaultDecl { +// pub span: Span, +// +// pub decl: DefaultDecl, +// } +// +// pub enum DefaultDecl { +// Class(ClassExpr), +// +// Fn(FnExpr), +// +// TsInterfaceDecl(TsInterfaceDecl), +// } +// +// pub enum ImportSpecifier { +// Specific(ImportSpecific), +// Default(ImportDefault), +// Namespace(ImportStarAs), +// } +// +// pub struct ImportDefault { +// pub span: Span, +// +// pub local: Ident, +// } +// pub struct ImportStarAs { +// pub span: Span, +// +// pub local: Ident, +// } +// pub struct ImportSpecific { +// pub span: Span, +// +// pub local: Ident, +// +// pub imported: Option, +// } +// +// pub enum ExportSpecifier { +// Namespace(NamespaceExportSpecifier), +// +// Default(DefaultExportSpecifier), +// +// Named(NamedExportSpecifier), +// } +// +// pub struct NamespaceExportSpecifier { +// pub span: Span, +// +// pub name: Ident, +// } +// +// pub struct DefaultExportSpecifier { +// pub exported: Ident, +// } +// +// pub struct NamedExportSpecifier { +// pub span: Span, +// pub orig: Ident, +// pub exported: Option, +// } +// +// pub enum BinaryOp { +// EqEq, +// NotEq, +// EqEqEq, +// NotEqEq, +// Lt, +// LtEq, +// Gt, +// GtEq, +// LShift, +// RShift, +// ZeroFillRShift, +// +// Add, +// Sub, +// Mul, +// Div, +// Mod, +// +// BitOr, +// BitXor, +// BitAnd, +// +// LogicalOr, +// +// LogicalAnd, +// +// In, +// InstanceOf, +// +// Exp, +// +// NullishCoalescing, +// } +// +// pub enum AssignOp { +// Assign, +// AddAssign, +// SubAssign, +// MulAssign, +// DivAssign, +// ModAssign, +// LShiftAssign, +// RShiftAssign, +// ZeroFillRShiftAssign, +// BitOrAssign, +// BitXorAssign, +// BitAndAssign, +// +// ExpAssign, +// } +// +// pub enum UpdateOp { +// PlusPlus, +// MinusMinus, +// } +// +// pub enum UnaryOp { +// Minus, +// Plus, +// Bang, +// Tilde, +// TypeOf, +// Void, +// Delete, +// } +// +// pub enum Pat { +// Ident(Ident), +// +// Array(ArrayPat), +// +// Rest(RestPat), +// +// Object(ObjectPat), +// +// Assign(AssignPat), +// +// Invalid(Invalid), +// +// Expr(Box), +// } +// +// pub struct ArrayPat { +// pub span: Span, +// +// pub elems: Vec>, +// +// pub optional: bool, +// +// pub type_ann: Option, +// } +// +// pub struct ObjectPat { +// pub span: Span, +// +// pub props: Vec, +// +// pub optional: bool, +// +// pub type_ann: Option, +// } +// +// pub struct AssignPat { +// pub span: Span, +// +// pub left: Box, +// +// pub right: Box, +// +// pub type_ann: Option, +// } +// +// pub struct RestPat { +// pub span: Span, +// +// pub dot3_token: Span, +// +// pub arg: Box, +// +// pub type_ann: Option, +// } +// +// pub enum ObjectPatProp { +// KeyValue(KeyValuePatProp), +// +// Assign(AssignPatProp), +// +// Rest(RestPat), +// } +// +// pub struct KeyValuePatProp { +// pub key: PropName, +// +// pub value: Box, +// } +// pub struct AssignPatProp { +// pub span: Span, +// pub key: Ident, +// +// pub value: Option>, +// } +// +// pub enum Prop { +// Shorthand(Ident), +// +// KeyValue(KeyValueProp), +// +// Assign(AssignProp), +// +// Getter(GetterProp), +// +// Setter(SetterProp), +// +// Method(MethodProp), +// } +// +// pub struct KeyValueProp { +// pub key: PropName, +// +// pub value: Box, +// } +// +// pub struct AssignProp { +// pub key: Ident, +// pub value: Box, +// } +// +// pub struct GetterProp { +// pub span: Span, +// pub key: PropName, +// pub type_ann: Option, +// pub body: Option, +// } +// pub struct SetterProp { +// pub span: Span, +// pub key: PropName, +// pub param: Pat, +// pub body: Option, +// } +// pub struct MethodProp { +// pub key: PropName, +// +// pub function: Function, +// } +// +// pub enum PropName { +// Ident(Ident), +// Str(Str), +// Num(Number), +// Computed(ComputedPropName), +// } +// +// pub struct ComputedPropName { +// pub span: Span, +// pub expr: Box, +// } +// use crate::{ +// decl::{Decl, VarDecl}, +// expr::Expr, +// ident::Ident, +// pat::Pat, +// }; +// +// pub struct BlockStmt { +// pub span: Span, +// +// pub stmts: Vec, +// } +// +// pub enum Stmt { +// Block(BlockStmt), +// +// Empty(EmptyStmt), +// +// Debugger(DebuggerStmt), +// +// With(WithStmt), +// +// Return(ReturnStmt), +// +// Labeled(LabeledStmt), +// +// Break(BreakStmt), +// +// Continue(ContinueStmt), +// +// If(IfStmt), +// +// Switch(SwitchStmt), +// +// Throw(ThrowStmt), +// +// Try(TryStmt), +// +// While(WhileStmt), +// +// DoWhile(DoWhileStmt), +// +// For(ForStmt), +// +// ForIn(ForInStmt), +// +// ForOf(ForOfStmt), +// +// Decl(Decl), +// +// Expr(ExprStmt), +// } +// +// pub struct ExprStmt { +// pub span: Span, +// pub expr: Box, +// } +// +// pub struct EmptyStmt { +// pub span: Span, +// } +// +// pub struct DebuggerStmt { +// pub span: Span, +// } +// +// pub struct WithStmt { +// pub span: Span, +// pub obj: Box, +// pub body: Box, +// } +// +// pub struct ReturnStmt { +// pub span: Span, +// pub arg: Option>, +// } +// +// pub struct LabeledStmt { +// pub span: Span, +// pub label: Ident, +// pub body: Box, +// } +// +// pub struct BreakStmt { +// pub span: Span, +// pub label: Option, +// } +// +// pub struct ContinueStmt { +// pub span: Span, +// pub label: Option, +// } +// +// pub struct IfStmt { +// pub span: Span, +// pub test: Box, +// +// pub cons: Box, +// +// pub alt: Option>, +// } +// +// pub struct SwitchStmt { +// pub span: Span, +// pub discriminant: Box, +// pub cases: Vec, +// } +// +// pub struct ThrowStmt { +// pub span: Span, +// pub arg: Box, +// } +// +// pub struct TryStmt { +// pub span: Span, +// +// pub block: BlockStmt, +// +// pub handler: Option, +// +// pub finalizer: Option, +// } +// +// pub struct WhileStmt { +// pub span: Span, +// pub test: Box, +// pub body: Box, +// } +// +// pub struct DoWhileStmt { +// pub span: Span, +// pub test: Box, +// pub body: Box, +// } +// +// pub struct ForStmt { +// pub span: Span, +// +// pub init: Option, +// +// pub test: Option>, +// +// pub update: Option>, +// +// pub body: Box, +// } +// +// pub struct ForInStmt { +// pub span: Span, +// pub left: VarDeclOrPat, +// pub right: Box, +// pub body: Box, +// } +// +// pub struct ForOfStmt { +// pub span: Span, +// pub await_token: Option, +// pub left: VarDeclOrPat, +// pub right: Box, +// pub body: Box, +// } +// +// pub struct SwitchCase { +// pub span: Span, +// +// pub test: Option>, +// +// pub cons: Vec, +// } +// +// pub struct CatchClause { +// pub span: Span, +// pub param: Option, +// +// pub body: BlockStmt, +// } +// +// pub enum VarDeclOrPat { +// VarDecl(VarDecl), +// +// Pat(Pat), +// } +// +// pub enum VarDeclOrExpr { +// VarDecl(VarDecl), +// +// Expr(Box), +// } +// +// pub struct TsTypeAnn { +// pub span: Span, +// pub type_ann: Box, +// } +// +// pub struct TsTypeParamDecl { +// pub span: Span, +// pub params: Vec, +// } +// +// pub struct TsTypeParam { +// pub span: Span, +// pub name: Ident, +// +// pub constraint: Option>, +// +// pub default: Option>, +// } +// +// pub struct TsTypeParamInstantiation { +// pub span: Span, +// pub params: Vec>, +// } +// +// pub struct TsTypeCastExpr { +// pub span: Span, +// pub expr: Box, +// pub type_ann: TsTypeAnn, +// } +// +// pub struct TsParamProp { +// pub span: Span, +// pub decorators: Vec, +// pub accessibility: Option, +// pub readonly: bool, +// pub param: TsParamPropParam, +// } +// +// pub enum TsParamPropParam { +// Ident(Ident), +// +// Assign(AssignPat), +// } +// +// pub struct TsQualifiedName { +// pub left: TsEntityName, +// pub right: Ident, +// } +// +// pub enum TsEntityName { +// TsQualifiedName(Box), +// +// Ident(Ident), +// } +// +// pub enum TsSignatureDecl { +// TsCallSignatureDecl(TsCallSignatureDecl), +// +// TsConstructSignatureDecl(TsConstructSignatureDecl), +// +// TsMethodSignature(TsMethodSignature), +// +// TsFnType(TsFnType), +// +// TsConstructorType(TsConstructorType), +// } +// +// pub enum TsTypeElement { +// TsCallSignatureDecl(TsCallSignatureDecl), +// +// TsConstructSignatureDecl(TsConstructSignatureDecl), +// +// TsPropertySignature(TsPropertySignature), +// +// TsMethodSignature(TsMethodSignature), +// +// TsIndexSignature(TsIndexSignature), +// } +// +// pub struct TsCallSignatureDecl { +// pub span: Span, +// pub params: Vec, +// pub type_ann: Option, +// pub type_params: Option, +// } +// +// pub struct TsConstructSignatureDecl { +// pub span: Span, +// pub params: Vec, +// pub type_ann: Option, +// pub type_params: Option, +// } +// +// pub struct TsPropertySignature { +// pub span: Span, +// pub readonly: bool, +// pub key: Box, +// pub computed: bool, +// pub optional: bool, +// pub init: Option>, +// pub params: Vec, +// pub type_ann: Option, +// pub type_params: Option, +// } +// +// pub struct TsMethodSignature { +// pub span: Span, +// pub readonly: bool, +// pub key: Box, +// pub computed: bool, +// pub optional: bool, +// pub params: Vec, +// pub type_ann: Option, +// pub type_params: Option, +// } +// +// pub struct TsIndexSignature { +// pub params: Vec, +// pub type_ann: Option, +// +// pub readonly: bool, +// pub span: Span, +// } +// +// pub enum TsType { +// TsKeywordType(TsKeywordType), +// +// TsThisType(TsThisType), +// +// TsFnOrConstructorType(TsFnOrConstructorType), +// +// TsTypeRef(TsTypeRef), +// +// TsTypeQuery(TsTypeQuery), +// +// TsTypeLit(TsTypeLit), +// +// TsArrayType(TsArrayType), +// +// TsTupleType(TsTupleType), +// +// TsOptionalType(TsOptionalType), +// +// TsRestType(TsRestType), +// +// TsUnionOrIntersectionType(TsUnionOrIntersectionType), +// +// TsConditionalType(TsConditionalType), +// +// TsInferType(TsInferType), +// +// TsParenthesizedType(TsParenthesizedType), +// +// TsTypeOperator(TsTypeOperator), +// +// TsIndexedAccessType(TsIndexedAccessType), +// +// TsMappedType(TsMappedType), +// +// TsLitType(TsLitType), +// +// TsTypePredicate(TsTypePredicate), +// +// TsImportType(TsImportType), +// } +// +// pub enum TsFnOrConstructorType { +// TsFnType(TsFnType), +// TsConstructorType(TsConstructorType), +// } +// +// impl From for TsType { +// fn from(t: TsFnType) -> Self { +// TsFnOrConstructorType::TsFnType(t).into() +// } +// } +// +// impl From for TsType { +// fn from(t: TsConstructorType) -> Self { +// TsFnOrConstructorType::TsConstructorType(t).into() +// } +// } +// +// impl From for TsType { +// fn from(t: TsUnionType) -> Self { +// TsUnionOrIntersectionType::TsUnionType(t).into() +// } +// } +// +// impl From for TsType { +// fn from(t: TsIntersectionType) -> Self { +// TsUnionOrIntersectionType::TsIntersectionType(t).into() +// } +// } +// +// pub struct TsKeywordType { +// pub span: Span, +// pub kind: TsKeywordTypeKind, +// } +// +// pub enum TsKeywordTypeKind { +// TsAnyKeyword, +// +// TsUnknownKeyword, +// +// TsNumberKeyword, +// +// TsObjectKeyword, +// +// TsBooleanKeyword, +// +// TsBigIntKeyword, +// +// TsStringKeyword, +// +// TsSymbolKeyword, +// +// TsVoidKeyword, +// +// TsUndefinedKeyword, +// +// TsNullKeyword, +// +// TsNeverKeyword, +// } +// +// pub struct TsThisType { +// pub span: Span, +// } +// +// pub enum TsFnParam { +// Ident(Ident), +// +// Array(ArrayPat), +// +// Rest(RestPat), +// +// Object(ObjectPat), +// } +// +// pub struct TsFnType { +// pub span: Span, +// pub params: Vec, +// +// pub type_params: Option, +// pub type_ann: TsTypeAnn, +// } +// +// pub struct TsConstructorType { +// pub span: Span, +// pub params: Vec, +// pub type_params: Option, +// pub type_ann: TsTypeAnn, +// } +// +// pub struct TsTypeRef { +// pub span: Span, +// pub type_name: TsEntityName, +// pub type_params: Option, +// } +// +// pub struct TsTypePredicate { +// pub span: Span, +// pub asserts: bool, +// pub param_name: TsThisTypeOrIdent, +// pub type_ann: Option, +// } +// +// pub enum TsThisTypeOrIdent { +// TsThisType(TsThisType), +// +// Ident(Ident), +// } +// +// pub struct TsTypeQuery { +// pub span: Span, +// pub expr_name: TsTypeQueryExpr, +// } +// +// pub enum TsTypeQueryExpr { +// TsEntityName(TsEntityName), +// Import(TsImportType), +// } +// +// pub struct TsImportType { +// pub span: Span, +// pub arg: Str, +// pub qualifier: Option, +// pub type_args: Option, +// } +// +// pub struct TsTypeLit { +// pub span: Span, +// pub members: Vec, +// } +// +// pub struct TsArrayType { +// pub span: Span, +// pub elem_type: Box, +// } +// +// pub struct TsTupleType { +// pub span: Span, +// pub elem_types: Vec>, +// } +// +// pub struct TsOptionalType { +// pub span: Span, +// pub type_ann: Box, +// } +// +// pub struct TsRestType { +// pub span: Span, +// pub type_ann: Box, +// } +// +// pub enum TsUnionOrIntersectionType { +// TsUnionType(TsUnionType), +// +// TsIntersectionType(TsIntersectionType), +// } +// +// pub struct TsUnionType { +// pub span: Span, +// pub types: Vec>, +// } +// +// pub struct TsIntersectionType { +// pub span: Span, +// pub types: Vec>, +// } +// +// pub struct TsConditionalType { +// pub span: Span, +// pub check_type: Box, +// pub extends_type: Box, +// pub true_type: Box, +// pub false_type: Box, +// } +// +// pub struct TsInferType { +// pub span: Span, +// pub type_param: TsTypeParam, +// } +// +// pub struct TsParenthesizedType { +// pub span: Span, +// pub type_ann: Box, +// } +// +// pub struct TsTypeOperator { +// pub span: Span, +// pub op: TsTypeOperatorOp, +// pub type_ann: Box, +// } +// +// pub enum TsTypeOperatorOp { +// KeyOf, +// Unique, +// ReadOnly, +// } +// +// pub struct TsIndexedAccessType { +// pub span: Span, +// pub readonly: bool, +// pub obj_type: Box, +// pub index_type: Box, +// } +// +// pub enum TruePlusMinus { +// True, +// Plus, +// Minus, +// } +// +// impl Serialize for TruePlusMinus { +// fn serialize(&self, serializer: S) -> Result +// where +// S: ::serde::Serializer, +// { +// match *self { +// TruePlusMinus::True => serializer.serialize_bool(true), +// TruePlusMinus::Plus => serializer.serialize_str("+"), +// TruePlusMinus::Minus => serializer.serialize_str("-"), +// } +// } +// } +// +// impl<'de> Deserialize<'de> for TruePlusMinus { +// fn deserialize(deserializer: D) -> Result +// where +// D: Deserializer<'de>, +// { +// struct TruePlusMinusVisitor; +// +// impl<'de> Visitor<'de> for TruePlusMinusVisitor { +// type Value = TruePlusMinus; +// fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> +// fmt::Result { formatter.write_str("one of '+', '-', +// true") } +// +// fn visit_str(self, value: &str) -> Result +// where +// E: de::Error, +// { +// match value { +// "+" => Ok(TruePlusMinus::Plus), +// "-" => Ok(TruePlusMinus::Minus), +// "true" => Ok(TruePlusMinus::True), +// _ => +// Err(de::Error::invalid_value(Unexpected::Str(value), &self)), +// } } +// +// fn visit_bool(self, value: bool) -> Result +// where +// E: de::Error, +// { +// if value { +// Ok(TruePlusMinus::True) +// } else { +// Err(de::Error::invalid_value(Unexpected::Bool(value), +// &self)) } +// } +// } +// +// deserializer.deserialize_any(TruePlusMinusVisitor) +// } +// } +// +// pub struct TsMappedType { +// pub span: Span, +// pub readonly: Option, +// pub type_param: TsTypeParam, +// pub optional: Option, +// pub type_ann: Option>, +// } +// +// pub struct TsLitType { +// pub span: Span, +// pub lit: TsLit, +// } +// +// pub enum TsLit { +// Number(Number), +// +// Str(Str), +// +// Bool(Bool), +// } +// +// pub struct TsInterfaceDecl { +// pub span: Span, +// pub id: Ident, +// pub declare: bool, +// pub type_params: Option, +// pub extends: Vec, +// pub body: TsInterfaceBody, +// } +// +// pub struct TsInterfaceBody { +// pub span: Span, +// pub body: Vec, +// } +// +// pub struct TsExprWithTypeArgs { +// pub span: Span, +// pub expr: TsEntityName, +// pub type_args: Option, +// } +// +// pub struct TsTypeAliasDecl { +// pub span: Span, +// pub declare: bool, +// pub id: Ident, +// pub type_params: Option, +// pub type_ann: Box, +// } +// +// pub struct TsEnumDecl { +// pub span: Span, +// pub declare: bool, +// pub is_const: bool, +// pub id: Ident, +// pub members: Vec, +// } +// +// pub struct TsEnumMember { +// pub span: Span, +// pub id: TsEnumMemberId, +// pub init: Option>, +// } +// +// pub enum TsEnumMemberId { +// Ident(Ident), +// +// Str(Str), +// } +// +// pub struct TsModuleDecl { +// pub span: Span, +// pub declare: bool, +// pub global: bool, +// pub id: TsModuleName, +// pub body: Option, +// } +// +// pub enum TsNamespaceBody { +// TsModuleBlock(TsModuleBlock), +// +// TsNamespaceDecl(TsNamespaceDecl), +// } +// +// pub struct TsModuleBlock { +// pub span: Span, +// pub body: Vec, +// } +// +// pub struct TsNamespaceDecl { +// pub span: Span, +// pub declare: bool, +// pub global: bool, +// pub id: Ident, +// pub body: Box, +// } +// +// pub enum TsModuleName { +// Ident(Ident), +// +// Str(Str), +// } +// +// pub struct TsImportEqualsDecl { +// pub span: Span, +// pub declare: bool, +// pub is_export: bool, +// pub id: Ident, +// pub module_ref: TsModuleRef, +// } +// +// pub enum TsModuleRef { +// TsEntityName(TsEntityName), +// +// TsExternalModuleRef(TsExternalModuleRef), +// } +// +// pub struct TsExternalModuleRef { +// pub span: Span, +// pub expr: Str, +// } +// +// pub struct TsExportAssignment { +// pub span: Span, +// pub expr: Box, +// } +// +// pub struct TsNamespaceExportDecl { +// pub span: Span, +// pub id: Ident, +// } +// +// pub struct TsAsExpr { +// pub span: Span, +// pub expr: Box, +// pub type_ann: Box, +// } +// +// pub struct TsTypeAssertion { +// pub span: Span, +// pub expr: Box, +// pub type_ann: Box, +// } +// +// pub struct TsNonNullExpr { +// pub span: Span, +// pub expr: Box, +// } +// +// pub enum Accessibility { +// Public, +// Protected, +// Private, +// } +// +// pub struct TsConstAssertion { +// pub span: Span, +// pub expr: Box, +// } +// } From a24b940b00bbab89abcfc0e33f4a966063f5f5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 20:24:39 +0900 Subject: [PATCH 16/32] Fix method name --- ecmascript/visit/macros/src/lib.rs | 12 +-- ecmascript/visit/src/lib.rs | 147 +++++++++++++---------------- 2 files changed, 72 insertions(+), 87 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index e682e17ed5c8..b456209e7123 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -339,7 +339,7 @@ fn method_sig(type_name: &Ident) -> Signature { unsafety: None, abi: None, fn_token: def_site(), - ident: type_name.clone(), + ident: type_name.clone().new_ident_with(prefix_method_name), generics: Default::default(), paren_token: def_site(), inputs: { @@ -357,11 +357,11 @@ fn method_sig(type_name: &Ident) -> Signature { } } -fn method_name(v: &Type) -> Ident { - fn handle(v: &str) -> String { - format!("visit_{}", v.to_snake_case()) - } +fn prefix_method_name(v: &str) -> String { + format!("visit_{}", v.to_snake_case()) +} +fn method_name(v: &Type) -> Ident { match v { Type::Array(_) => unimplemented!("type: array type"), Type::BareFn(_) => unimplemented!("type: fn type"), @@ -373,7 +373,7 @@ fn method_name(v: &Type) -> Ident { Type::Paren(ty) => return method_name(&ty.elem), Type::Path(p) => { let last = p.path.segments.last().unwrap(); - let ident = last.ident.new_ident_with(handle); + let ident = last.ident.new_ident_with(prefix_method_name); if last.arguments.is_empty() { return ident; diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index 40e01cbdec25..d3b69063aee8 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -35,12 +35,75 @@ define!({ PrivateProp(PrivateProp), TsIndexSignature(TsIndexSignature), } + + pub struct ClassProp { + pub span: Span, + pub key: Box, + pub value: Option>, + pub type_ann: Option, + pub is_static: bool, + pub decorators: Vec, + pub computed: bool, + pub accessibility: Option, + pub is_abstract: bool, + pub is_optional: bool, + pub readonly: bool, + pub definite: bool, + } + pub struct PrivateProp { + pub span: Span, + pub key: PrivateName, + pub value: Option>, + pub type_ann: Option, + pub is_static: bool, + pub decorators: Vec, + pub computed: bool, + pub accessibility: Option, + pub is_abstract: bool, + pub is_optional: bool, + pub readonly: bool, + pub definite: bool, + } + pub struct ClassMethod { + pub span: Span, + pub key: PropName, + pub function: Function, + pub kind: MethodKind, + pub is_static: bool, + pub accessibility: Option, + pub is_abstract: bool, + pub is_optional: bool, + } + pub struct PrivateMethod { + pub span: Span, + pub key: PrivateName, + pub function: Function, + pub kind: MethodKind, + pub is_static: bool, + pub accessibility: Option, + pub is_abstract: bool, + pub is_optional: bool, + } + pub struct Constructor { + pub span: Span, + pub key: PropName, + pub params: Vec, + pub body: Option, + pub accessibility: Option, + pub is_optional: bool, + } + pub struct Decorator { + pub span: Span, + pub expr: Box, + } + pub enum MethodKind { + Method, + Getter, + Setter, + } }); // mod types { -// -// - // // macro_rules! property { // ($name:ident, $ty:literal, $KEY:ty) => { @@ -1394,30 +1457,6 @@ define!({ // TsConstructorType(TsConstructorType), // } // -// impl From for TsType { -// fn from(t: TsFnType) -> Self { -// TsFnOrConstructorType::TsFnType(t).into() -// } -// } -// -// impl From for TsType { -// fn from(t: TsConstructorType) -> Self { -// TsFnOrConstructorType::TsConstructorType(t).into() -// } -// } -// -// impl From for TsType { -// fn from(t: TsUnionType) -> Self { -// TsUnionOrIntersectionType::TsUnionType(t).into() -// } -// } -// -// impl From for TsType { -// fn from(t: TsIntersectionType) -> Self { -// TsUnionOrIntersectionType::TsIntersectionType(t).into() -// } -// } -// // pub struct TsKeywordType { // pub span: Span, // pub kind: TsKeywordTypeKind, @@ -1598,60 +1637,6 @@ define!({ // Minus, // } // -// impl Serialize for TruePlusMinus { -// fn serialize(&self, serializer: S) -> Result -// where -// S: ::serde::Serializer, -// { -// match *self { -// TruePlusMinus::True => serializer.serialize_bool(true), -// TruePlusMinus::Plus => serializer.serialize_str("+"), -// TruePlusMinus::Minus => serializer.serialize_str("-"), -// } -// } -// } -// -// impl<'de> Deserialize<'de> for TruePlusMinus { -// fn deserialize(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// struct TruePlusMinusVisitor; -// -// impl<'de> Visitor<'de> for TruePlusMinusVisitor { -// type Value = TruePlusMinus; -// fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> -// fmt::Result { formatter.write_str("one of '+', '-', -// true") } -// -// fn visit_str(self, value: &str) -> Result -// where -// E: de::Error, -// { -// match value { -// "+" => Ok(TruePlusMinus::Plus), -// "-" => Ok(TruePlusMinus::Minus), -// "true" => Ok(TruePlusMinus::True), -// _ => -// Err(de::Error::invalid_value(Unexpected::Str(value), &self)), -// } } -// -// fn visit_bool(self, value: bool) -> Result -// where -// E: de::Error, -// { -// if value { -// Ok(TruePlusMinus::True) -// } else { -// Err(de::Error::invalid_value(Unexpected::Bool(value), -// &self)) } -// } -// } -// -// deserializer.deserialize_any(TruePlusMinusVisitor) -// } -// } -// // pub struct TsMappedType { // pub span: Span, // pub readonly: Option, From d9c49facec8296d5faa023906a9012de061c034a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 20:25:38 +0900 Subject: [PATCH 17/32] Move code --- ecmascript/visit/macros/src/lib.rs | 50 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index b456209e7123..abc68a3978cd 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -260,6 +260,31 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { // } fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { + fn method_sig(type_name: &Ident) -> Signature { + Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: def_site(), + ident: type_name.clone().new_ident_with(prefix_method_name), + generics: Default::default(), + paren_token: def_site(), + inputs: { + let mut p = Punctuated::default(); + p.push_value(q!(Vars {}, { &self }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars { Type: type_name }, { n: &Type }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); + + p + }, + variadic: None, + output: ReturnType::Default, + } + } + match e { Item::Struct(s) => { let type_name = &s.ident; @@ -332,31 +357,6 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { } } -fn method_sig(type_name: &Ident) -> Signature { - Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: def_site(), - ident: type_name.clone().new_ident_with(prefix_method_name), - generics: Default::default(), - paren_token: def_site(), - inputs: { - let mut p = Punctuated::default(); - p.push_value(q!(Vars {}, { &self }).parse()); - p.push_punct(def_site()); - p.push_value(q!(Vars { Type: type_name }, { n: &Type }).parse()); - p.push_punct(def_site()); - p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); - - p - }, - variadic: None, - output: ReturnType::Default, - } -} - fn prefix_method_name(v: &str) -> String { format!("visit_{}", v.to_snake_case()) } From 38d11f348a95b93dc3f23c608430e2f7e1572830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 20:31:49 +0900 Subject: [PATCH 18/32] Cleanup --- ecmascript/visit/macros/src/lib.rs | 5 +- ecmascript/visit/src/lib.rs | 2845 +++++++++++----------------- 2 files changed, 1128 insertions(+), 1722 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index abc68a3978cd..d5e2f2a440bb 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -353,7 +353,10 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { } } - _ => unimplemented!("proper error reporting for item other than struct / enum"), + _ => unimplemented!( + "proper error reporting for item other than struct / enum: {:?}", + e + ), } } diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index d3b69063aee8..e88442c1fd59 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -9,33 +9,6 @@ pub trait Node: Any {} impl Node for T where T: Any {} define!({ - pub struct Class { - pub span: Span, - - pub decorators: Vec, - - pub body: Vec, - - pub super_class: Option>, - - pub is_abstract: bool, - - pub type_params: Option, - - pub super_type_params: Option, - - pub implements: Vec, - } - - pub enum ClassMember { - Constructor(Constructor), - Method(ClassMethod), - PrivateMethod(PrivateMethod), - ClassProp(ClassProp), - PrivateProp(PrivateProp), - TsIndexSignature(TsIndexSignature), - } - pub struct ClassProp { pub span: Span, pub key: Box, @@ -101,1698 +74,1128 @@ define!({ Getter, Setter, } + pub enum Decl { + Class(ClassDecl), + Fn(FnDecl), + Var(VarDecl), + TsInterface(TsInterfaceDecl), + TsTypeAlias(TsTypeAliasDecl), + TsEnum(TsEnumDecl), + TsModule(TsModuleDecl), + } + pub struct FnDecl { + pub ident: Ident, + pub declare: bool, + pub function: Function, + } + pub struct ClassDecl { + pub ident: Ident, + pub declare: bool, + pub class: Class, + } + pub struct VarDecl { + pub span: Span, + pub kind: VarDeclKind, + pub declare: bool, + pub decls: Vec, + } + pub enum VarDeclKind { + Var, + Let, + Const, + } + pub struct VarDeclarator { + pub span: Span, + pub name: Pat, + pub init: Option>, + pub definite: bool, + } + pub enum Expr { + This(ThisExpr), + Array(ArrayLit), + Object(ObjectLit), + Fn(FnExpr), + Unary(UnaryExpr), + Update(UpdateExpr), + Bin(BinExpr), + Assign(AssignExpr), + Member(MemberExpr), + Cond(CondExpr), + Call(CallExpr), + New(NewExpr), + Seq(SeqExpr), + Ident(Ident), + Lit(Lit), + Tpl(Tpl), + TaggedTpl(TaggedTpl), + Arrow(ArrowExpr), + Class(ClassExpr), + Yield(YieldExpr), + MetaProp(MetaPropExpr), + Await(AwaitExpr), + Paren(ParenExpr), + JSXMember(JSXMemberExpr), + JSXNamespacedName(JSXNamespacedName), + JSXEmpty(JSXEmptyExpr), + JSXElement(Box), + JSXFragment(JSXFragment), + TsTypeAssertion(TsTypeAssertion), + TsConstAssertion(TsConstAssertion), + TsNonNull(TsNonNullExpr), + TsTypeCast(TsTypeCastExpr), + TsAs(TsAsExpr), + PrivateName(PrivateName), + OptChain(OptChainExpr), + Invalid(Invalid), + } + pub struct ThisExpr { + pub span: Span, + } + pub struct ArrayLit { + pub span: Span, + pub elems: Vec>, + } + pub struct ObjectLit { + pub span: Span, + pub props: Vec, + } + pub enum PropOrSpread { + Spread(SpreadElement), + Prop(Box), + } + pub struct SpreadElement { + pub dot3_token: Span, + pub expr: Box, + } + pub struct UnaryExpr { + pub span: Span, + pub op: UnaryOp, + pub arg: Box, + } + pub struct UpdateExpr { + pub span: Span, + pub op: UpdateOp, + pub prefix: bool, + pub arg: Box, + } + pub struct BinExpr { + pub span: Span, + pub op: BinaryOp, + pub left: Box, + pub right: Box, + } + pub struct FnExpr { + pub ident: Option, + pub function: Function, + } + pub struct ClassExpr { + pub ident: Option, + pub class: Class, + } + pub struct AssignExpr { + pub span: Span, + pub op: AssignOp, + pub left: PatOrExpr, + pub right: Box, + } + pub struct MemberExpr { + pub span: Span, + pub obj: ExprOrSuper, + pub prop: Box, + pub computed: bool, + } + pub struct CondExpr { + pub span: Span, + pub test: Box, + pub cons: Box, + pub alt: Box, + } + pub struct CallExpr { + pub span: Span, + pub callee: ExprOrSuper, + pub args: Vec, + pub type_args: Option, + } + pub struct NewExpr { + pub span: Span, + pub callee: Box, + pub args: Option>, + pub type_args: Option, + } + pub struct SeqExpr { + pub span: Span, + pub exprs: Vec>, + } + pub struct ArrowExpr { + pub span: Span, + pub params: Vec, + pub body: BlockStmtOrExpr, + pub is_async: bool, + pub is_generator: bool, + pub type_params: Option, + pub return_type: Option, + } + pub struct YieldExpr { + pub span: Span, + pub arg: Option>, + pub delegate: bool, + } + pub struct MetaPropExpr { + pub meta: Ident, + pub prop: Ident, + } + pub struct AwaitExpr { + pub span: Span, + pub arg: Box, + } + pub struct Tpl { + pub span: Span, + pub exprs: Vec>, + pub quasis: Vec, + } + pub struct TaggedTpl { + pub span: Span, + pub tag: Box, + pub exprs: Vec>, + pub quasis: Vec, + pub type_params: Option, + } + pub struct TplElement { + pub span: Span, + pub tail: bool, + pub cooked: Option, + pub raw: Str, + } + pub struct ParenExpr { + pub span: Span, + pub expr: Box, + } + pub enum ExprOrSuper { + Super(Super), + Expr(Box), + } + pub struct Super { + pub span: Span, + } + pub struct ExprOrSpread { + pub spread: Option, + pub expr: Box, + } + pub enum BlockStmtOrExpr { + BlockStmt(BlockStmt), + Expr(Box), + } + pub enum PatOrExpr { + Expr(Box), + Pat(Box), + } + pub struct OptChainExpr { + pub span: Span, + pub expr: Box, + } + pub struct Function { + pub params: Vec, + pub decorators: Vec, + pub span: Span, + pub body: Option, + pub is_generator: bool, + pub is_async: bool, + pub type_params: Option, + pub return_type: Option, + } + pub enum PatOrTsParamProp { + TsParamProp(TsParamProp), + Pat(Pat), + } + pub struct Ident { + pub span: Span, + pub sym: JsWord, + pub type_ann: Option, + pub optional: bool, + } + pub struct PrivateName { + pub span: Span, + pub id: Ident, + } + pub enum JSXObject { + JSXMemberExpr(Box), + Ident(Ident), + } + pub struct JSXMemberExpr { + pub obj: JSXObject, + pub prop: Ident, + } + pub struct JSXNamespacedName { + pub ns: Ident, + pub name: Ident, + } + pub struct JSXEmptyExpr { + pub span: Span, + } + pub struct JSXExprContainer { + pub span: Span, + pub expr: JSXExpr, + } + pub enum JSXExpr { + JSXEmptyExpr(JSXEmptyExpr), + Expr(Box), + } + pub struct JSXSpreadChild { + pub span: Span, + pub expr: Box, + } + pub enum JSXElementName { + Ident(Ident), + JSXMemberExpr(JSXMemberExpr), + JSXNamespacedName(JSXNamespacedName), + } + pub struct JSXOpeningElement { + pub name: JSXElementName, + pub span: Span, + pub attrs: Vec, + pub self_closing: bool, + pub type_args: Option, + } + pub enum JSXAttrOrSpread { + JSXAttr(JSXAttr), + SpreadElement(SpreadElement), + } + pub struct JSXClosingElement { + pub span: Span, + pub name: JSXElementName, + } + pub struct JSXAttr { + pub span: Span, + pub name: JSXAttrName, + pub value: Option, + } + pub enum JSXAttrName { + Ident(Ident), + JSXNamespacedName(JSXNamespacedName), + } + pub enum JSXAttrValue { + Lit(Lit), + JSXExprContainer(JSXExprContainer), + JSXElement(Box), + JSXFragment(JSXFragment), + } + pub struct JSXText { + pub span: Span, + pub value: JsWord, + pub raw: JsWord, + } + pub struct JSXElement { + pub span: Span, + pub opening: JSXOpeningElement, + pub children: Vec, + pub closing: Option, + } + pub enum JSXElementChild { + JSXText(JSXText), + JSXExprContainer(JSXExprContainer), + JSXSpreadChild(JSXSpreadChild), + JSXElement(Box), + JSXFragment(JSXFragment), + } + pub struct JSXFragment { + pub span: Span, + pub opening: JSXOpeningFragment, + pub children: Vec, + pub closing: JSXClosingFragment, + } + pub struct JSXOpeningFragment { + pub span: Span, + } + pub struct JSXClosingFragment { + pub span: Span, + } + pub struct Invalid { + pub span: Span, + } + pub enum Lit { + Str(Str), + Bool(Bool), + Null(Null), + Num(Number), + BigInt(BigInt), + Regex(Regex), + JSXText(JSXText), + } + pub struct BigInt { + pub span: Span, + pub value: BigIntValue, + } + pub struct Str { + pub span: Span, + pub value: JsWord, + pub has_escape: bool, + } + pub struct Bool { + pub span: Span, + pub value: bool, + } + pub struct Null { + pub span: Span, + } + pub struct Regex { + pub span: Span, + pub exp: JsWord, + pub flags: JsWord, + } + pub struct Number { + pub span: Span, + pub value: f64, + } + pub enum Program { + Module(Module), + Script(Script), + } + pub struct Module { + pub span: Span, + pub body: Vec, + pub shebang: Option, + } + pub struct Script { + pub span: Span, + pub body: Vec, + pub shebang: Option, + } + pub enum ModuleItem { + ModuleDecl(ModuleDecl), + Stmt(Stmt), + } + pub enum ModuleDecl { + Import(ImportDecl), + ExportDecl(ExportDecl), + ExportNamed(NamedExport), + ExportDefaultDecl(ExportDefaultDecl), + ExportDefaultExpr(ExportDefaultExpr), + ExportAll(ExportAll), + TsImportEquals(TsImportEqualsDecl), + TsExportAssignment(TsExportAssignment), + TsNamespaceExport(TsNamespaceExportDecl), + } + pub struct ExportDefaultExpr { + pub span: Span, + pub expr: Box, + } + pub struct ExportDecl { + pub span: Span, + pub decl: Decl, + } + pub struct ImportDecl { + pub span: Span, + pub specifiers: Vec, + pub src: Str, + pub type_only: bool, + } + pub struct ExportAll { + pub span: Span, + pub src: Str, + } + pub struct NamedExport { + pub span: Span, + pub specifiers: Vec, + pub src: Option, + pub type_only: bool, + } + pub struct ExportDefaultDecl { + pub span: Span, + pub decl: DefaultDecl, + } + pub enum DefaultDecl { + Class(ClassExpr), + Fn(FnExpr), + TsInterfaceDecl(TsInterfaceDecl), + } + pub enum ImportSpecifier { + Specific(ImportSpecific), + Default(ImportDefault), + Namespace(ImportStarAs), + } + pub struct ImportDefault { + pub span: Span, + pub local: Ident, + } + pub struct ImportStarAs { + pub span: Span, + pub local: Ident, + } + pub struct ImportSpecific { + pub span: Span, + pub local: Ident, + pub imported: Option, + } + pub enum ExportSpecifier { + Namespace(NamespaceExportSpecifier), + Default(DefaultExportSpecifier), + Named(NamedExportSpecifier), + } + pub struct NamespaceExportSpecifier { + pub span: Span, + pub name: Ident, + } + pub struct DefaultExportSpecifier { + pub exported: Ident, + } + pub struct NamedExportSpecifier { + pub span: Span, + pub orig: Ident, + pub exported: Option, + } + pub enum BinaryOp { + EqEq, + NotEq, + EqEqEq, + NotEqEq, + Lt, + LtEq, + Gt, + GtEq, + LShift, + RShift, + ZeroFillRShift, + Add, + Sub, + Mul, + Div, + Mod, + BitOr, + BitXor, + BitAnd, + LogicalOr, + LogicalAnd, + In, + InstanceOf, + Exp, + NullishCoalescing, + } + pub enum AssignOp { + Assign, + AddAssign, + SubAssign, + MulAssign, + DivAssign, + ModAssign, + LShiftAssign, + RShiftAssign, + ZeroFillRShiftAssign, + BitOrAssign, + BitXorAssign, + BitAndAssign, + ExpAssign, + } + pub enum UpdateOp { + PlusPlus, + MinusMinus, + } + pub enum UnaryOp { + Minus, + Plus, + Bang, + Tilde, + TypeOf, + Void, + Delete, + } + pub enum Pat { + Ident(Ident), + Array(ArrayPat), + Rest(RestPat), + Object(ObjectPat), + Assign(AssignPat), + Invalid(Invalid), + Expr(Box), + } + pub struct ArrayPat { + pub span: Span, + pub elems: Vec>, + pub optional: bool, + pub type_ann: Option, + } + pub struct ObjectPat { + pub span: Span, + pub props: Vec, + pub optional: bool, + pub type_ann: Option, + } + pub struct AssignPat { + pub span: Span, + pub left: Box, + pub right: Box, + pub type_ann: Option, + } + pub struct RestPat { + pub span: Span, + pub dot3_token: Span, + pub arg: Box, + pub type_ann: Option, + } + pub enum ObjectPatProp { + KeyValue(KeyValuePatProp), + Assign(AssignPatProp), + Rest(RestPat), + } + pub struct KeyValuePatProp { + pub key: PropName, + pub value: Box, + } + pub struct AssignPatProp { + pub span: Span, + pub key: Ident, + pub value: Option>, + } + pub enum Prop { + Shorthand(Ident), + KeyValue(KeyValueProp), + Assign(AssignProp), + Getter(GetterProp), + Setter(SetterProp), + Method(MethodProp), + } + pub struct KeyValueProp { + pub key: PropName, + pub value: Box, + } + pub struct AssignProp { + pub key: Ident, + pub value: Box, + } + pub struct GetterProp { + pub span: Span, + pub key: PropName, + pub type_ann: Option, + pub body: Option, + } + pub struct SetterProp { + pub span: Span, + pub key: PropName, + pub param: Pat, + pub body: Option, + } + pub struct MethodProp { + pub key: PropName, + pub function: Function, + } + pub enum PropName { + Ident(Ident), + Str(Str), + Num(Number), + Computed(ComputedPropName), + } + pub struct ComputedPropName { + pub span: Span, + pub expr: Box, + } + pub struct BlockStmt { + pub span: Span, + pub stmts: Vec, + } + pub enum Stmt { + Block(BlockStmt), + Empty(EmptyStmt), + Debugger(DebuggerStmt), + With(WithStmt), + Return(ReturnStmt), + Labeled(LabeledStmt), + Break(BreakStmt), + Continue(ContinueStmt), + If(IfStmt), + Switch(SwitchStmt), + Throw(ThrowStmt), + Try(TryStmt), + While(WhileStmt), + DoWhile(DoWhileStmt), + For(ForStmt), + ForIn(ForInStmt), + ForOf(ForOfStmt), + Decl(Decl), + Expr(ExprStmt), + } + pub struct ExprStmt { + pub span: Span, + pub expr: Box, + } + pub struct EmptyStmt { + pub span: Span, + } + pub struct DebuggerStmt { + pub span: Span, + } + pub struct WithStmt { + pub span: Span, + pub obj: Box, + pub body: Box, + } + pub struct ReturnStmt { + pub span: Span, + pub arg: Option>, + } + pub struct LabeledStmt { + pub span: Span, + pub label: Ident, + pub body: Box, + } + pub struct BreakStmt { + pub span: Span, + pub label: Option, + } + pub struct ContinueStmt { + pub span: Span, + pub label: Option, + } + pub struct IfStmt { + pub span: Span, + pub test: Box, + pub cons: Box, + pub alt: Option>, + } + pub struct SwitchStmt { + pub span: Span, + pub discriminant: Box, + pub cases: Vec, + } + pub struct ThrowStmt { + pub span: Span, + pub arg: Box, + } + pub struct TryStmt { + pub span: Span, + pub block: BlockStmt, + pub handler: Option, + pub finalizer: Option, + } + pub struct WhileStmt { + pub span: Span, + pub test: Box, + pub body: Box, + } + pub struct DoWhileStmt { + pub span: Span, + pub test: Box, + pub body: Box, + } + pub struct ForStmt { + pub span: Span, + pub init: Option, + pub test: Option>, + pub update: Option>, + pub body: Box, + } + pub struct ForInStmt { + pub span: Span, + pub left: VarDeclOrPat, + pub right: Box, + pub body: Box, + } + pub struct ForOfStmt { + pub span: Span, + pub await_token: Option, + pub left: VarDeclOrPat, + pub right: Box, + pub body: Box, + } + pub struct SwitchCase { + pub span: Span, + pub test: Option>, + pub cons: Vec, + } + pub struct CatchClause { + pub span: Span, + pub param: Option, + pub body: BlockStmt, + } + pub enum VarDeclOrPat { + VarDecl(VarDecl), + Pat(Pat), + } + pub enum VarDeclOrExpr { + VarDecl(VarDecl), + Expr(Box), + } + pub struct TsTypeAnn { + pub span: Span, + pub type_ann: Box, + } + pub struct TsTypeParamDecl { + pub span: Span, + pub params: Vec, + } + pub struct TsTypeParam { + pub span: Span, + pub name: Ident, + pub constraint: Option>, + pub default: Option>, + } + pub struct TsTypeParamInstantiation { + pub span: Span, + pub params: Vec>, + } + pub struct TsTypeCastExpr { + pub span: Span, + pub expr: Box, + pub type_ann: TsTypeAnn, + } + pub struct TsParamProp { + pub span: Span, + pub decorators: Vec, + pub accessibility: Option, + pub readonly: bool, + pub param: TsParamPropParam, + } + pub enum TsParamPropParam { + Ident(Ident), + Assign(AssignPat), + } + pub struct TsQualifiedName { + pub left: TsEntityName, + pub right: Ident, + } + pub enum TsEntityName { + TsQualifiedName(Box), + Ident(Ident), + } + pub enum TsSignatureDecl { + TsCallSignatureDecl(TsCallSignatureDecl), + TsConstructSignatureDecl(TsConstructSignatureDecl), + TsMethodSignature(TsMethodSignature), + TsFnType(TsFnType), + TsConstructorType(TsConstructorType), + } + pub enum TsTypeElement { + TsCallSignatureDecl(TsCallSignatureDecl), + TsConstructSignatureDecl(TsConstructSignatureDecl), + TsPropertySignature(TsPropertySignature), + TsMethodSignature(TsMethodSignature), + TsIndexSignature(TsIndexSignature), + } + pub struct TsCallSignatureDecl { + pub span: Span, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + pub struct TsConstructSignatureDecl { + pub span: Span, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + pub struct TsPropertySignature { + pub span: Span, + pub readonly: bool, + pub key: Box, + pub computed: bool, + pub optional: bool, + pub init: Option>, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + pub struct TsMethodSignature { + pub span: Span, + pub readonly: bool, + pub key: Box, + pub computed: bool, + pub optional: bool, + pub params: Vec, + pub type_ann: Option, + pub type_params: Option, + } + pub struct TsIndexSignature { + pub params: Vec, + pub type_ann: Option, + pub readonly: bool, + pub span: Span, + } + pub enum TsType { + TsKeywordType(TsKeywordType), + TsThisType(TsThisType), + TsFnOrConstructorType(TsFnOrConstructorType), + TsTypeRef(TsTypeRef), + TsTypeQuery(TsTypeQuery), + TsTypeLit(TsTypeLit), + TsArrayType(TsArrayType), + TsTupleType(TsTupleType), + TsOptionalType(TsOptionalType), + TsRestType(TsRestType), + TsUnionOrIntersectionType(TsUnionOrIntersectionType), + TsConditionalType(TsConditionalType), + TsInferType(TsInferType), + TsParenthesizedType(TsParenthesizedType), + TsTypeOperator(TsTypeOperator), + TsIndexedAccessType(TsIndexedAccessType), + TsMappedType(TsMappedType), + TsLitType(TsLitType), + TsTypePredicate(TsTypePredicate), + TsImportType(TsImportType), + } + pub enum TsFnOrConstructorType { + TsFnType(TsFnType), + TsConstructorType(TsConstructorType), + } + pub struct TsKeywordType { + pub span: Span, + pub kind: TsKeywordTypeKind, + } + pub enum TsKeywordTypeKind { + TsAnyKeyword, + TsUnknownKeyword, + TsNumberKeyword, + TsObjectKeyword, + TsBooleanKeyword, + TsBigIntKeyword, + TsStringKeyword, + TsSymbolKeyword, + TsVoidKeyword, + TsUndefinedKeyword, + TsNullKeyword, + TsNeverKeyword, + } + pub struct TsThisType { + pub span: Span, + } + pub enum TsFnParam { + Ident(Ident), + Array(ArrayPat), + Rest(RestPat), + Object(ObjectPat), + } + pub struct TsFnType { + pub span: Span, + pub params: Vec, + pub type_params: Option, + pub type_ann: TsTypeAnn, + } + pub struct TsConstructorType { + pub span: Span, + pub params: Vec, + pub type_params: Option, + pub type_ann: TsTypeAnn, + } + pub struct TsTypeRef { + pub span: Span, + pub type_name: TsEntityName, + pub type_params: Option, + } + pub struct TsTypePredicate { + pub span: Span, + pub asserts: bool, + pub param_name: TsThisTypeOrIdent, + pub type_ann: Option, + } + pub enum TsThisTypeOrIdent { + TsThisType(TsThisType), + Ident(Ident), + } + pub struct TsTypeQuery { + pub span: Span, + pub expr_name: TsTypeQueryExpr, + } + pub enum TsTypeQueryExpr { + TsEntityName(TsEntityName), + Import(TsImportType), + } + pub struct TsImportType { + pub span: Span, + pub arg: Str, + pub qualifier: Option, + pub type_args: Option, + } + pub struct TsTypeLit { + pub span: Span, + pub members: Vec, + } + pub struct TsArrayType { + pub span: Span, + pub elem_type: Box, + } + pub struct TsTupleType { + pub span: Span, + pub elem_types: Vec>, + } + pub struct TsOptionalType { + pub span: Span, + pub type_ann: Box, + } + pub struct TsRestType { + pub span: Span, + pub type_ann: Box, + } + pub enum TsUnionOrIntersectionType { + TsUnionType(TsUnionType), + TsIntersectionType(TsIntersectionType), + } + pub struct TsUnionType { + pub span: Span, + pub types: Vec>, + } + pub struct TsIntersectionType { + pub span: Span, + pub types: Vec>, + } + pub struct TsConditionalType { + pub span: Span, + pub check_type: Box, + pub extends_type: Box, + pub true_type: Box, + pub false_type: Box, + } + pub struct TsInferType { + pub span: Span, + pub type_param: TsTypeParam, + } + pub struct TsParenthesizedType { + pub span: Span, + pub type_ann: Box, + } + pub struct TsTypeOperator { + pub span: Span, + pub op: TsTypeOperatorOp, + pub type_ann: Box, + } + pub enum TsTypeOperatorOp { + KeyOf, + Unique, + ReadOnly, + } + pub struct TsIndexedAccessType { + pub span: Span, + pub readonly: bool, + pub obj_type: Box, + pub index_type: Box, + } + pub enum TruePlusMinus { + True, + Plus, + Minus, + } + pub struct TsMappedType { + pub span: Span, + pub readonly: Option, + pub type_param: TsTypeParam, + pub optional: Option, + pub type_ann: Option>, + } + pub struct TsLitType { + pub span: Span, + pub lit: TsLit, + } + pub enum TsLit { + Number(Number), + Str(Str), + Bool(Bool), + } + pub struct TsInterfaceDecl { + pub span: Span, + pub id: Ident, + pub declare: bool, + pub type_params: Option, + pub extends: Vec, + pub body: TsInterfaceBody, + } + pub struct TsInterfaceBody { + pub span: Span, + pub body: Vec, + } + pub struct TsExprWithTypeArgs { + pub span: Span, + pub expr: TsEntityName, + pub type_args: Option, + } + pub struct TsTypeAliasDecl { + pub span: Span, + pub declare: bool, + pub id: Ident, + pub type_params: Option, + pub type_ann: Box, + } + pub struct TsEnumDecl { + pub span: Span, + pub declare: bool, + pub is_const: bool, + pub id: Ident, + pub members: Vec, + } + pub struct TsEnumMember { + pub span: Span, + pub id: TsEnumMemberId, + pub init: Option>, + } + pub enum TsEnumMemberId { + Ident(Ident), + Str(Str), + } + pub struct TsModuleDecl { + pub span: Span, + pub declare: bool, + pub global: bool, + pub id: TsModuleName, + pub body: Option, + } + pub enum TsNamespaceBody { + TsModuleBlock(TsModuleBlock), + TsNamespaceDecl(TsNamespaceDecl), + } + pub struct TsModuleBlock { + pub span: Span, + pub body: Vec, + } + pub struct TsNamespaceDecl { + pub span: Span, + pub declare: bool, + pub global: bool, + pub id: Ident, + pub body: Box, + } + pub enum TsModuleName { + Ident(Ident), + Str(Str), + } + pub struct TsImportEqualsDecl { + pub span: Span, + pub declare: bool, + pub is_export: bool, + pub id: Ident, + pub module_ref: TsModuleRef, + } + pub enum TsModuleRef { + TsEntityName(TsEntityName), + TsExternalModuleRef(TsExternalModuleRef), + } + pub struct TsExternalModuleRef { + pub span: Span, + pub expr: Str, + } + pub struct TsExportAssignment { + pub span: Span, + pub expr: Box, + } + pub struct TsNamespaceExportDecl { + pub span: Span, + pub id: Ident, + } + pub struct TsAsExpr { + pub span: Span, + pub expr: Box, + pub type_ann: Box, + } + pub struct TsTypeAssertion { + pub span: Span, + pub expr: Box, + pub type_ann: Box, + } + pub struct TsNonNullExpr { + pub span: Span, + pub expr: Box, + } + pub enum Accessibility { + Public, + Protected, + Private, + } + pub struct TsConstAssertion { + pub span: Span, + pub expr: Box, + } }); - -// mod types { -// -// macro_rules! property { -// ($name:ident, $ty:literal, $KEY:ty) => { -// pub struct $name { -// pub span: Span, -// -// pub key: $KEY, -// -// pub value: Option>, -// -// pub type_ann: Option, -// -// pub is_static: bool, -// -// pub decorators: Vec, -// -// pub computed: bool, -// -// pub accessibility: Option, -// -// pub is_abstract: bool, -// -// pub is_optional: bool, -// -// pub readonly: bool, -// -// pub definite: bool, -// } -// }; -// } -// -// property!(ClassProp, "ClassProperty", Box); -// property!(PrivateProp, "PrivateProperty", PrivateName); -// -// macro_rules! method { -// ($name:ident, $ty:literal, $KEY:ty) => { -// pub struct $name { -// pub span: Span, -// -// pub key: $KEY, -// -// pub function: Function, -// -// pub kind: MethodKind, -// -// pub is_static: bool, -// -// pub accessibility: Option, -// -// pub is_abstract: bool, -// -// pub is_optional: bool, -// } -// }; -// } -// -// method!(ClassMethod, "ClassMethod", PropName); -// method!(PrivateMethod, "PrivateMethod", PrivateName); -// -// pub struct Constructor { -// pub span: Span, -// -// pub key: PropName, -// -// pub params: Vec, -// -// pub body: Option, -// -// pub accessibility: Option, -// -// pub is_optional: bool, -// } -// -// pub struct Decorator { -// pub span: Span, -// -// pub expr: Box, -// } -// -// pub enum MethodKind { -// Method, -// Getter, -// Setter, -// } -// -// pub enum Decl { -// Class(ClassDecl), -// Fn(FnDecl), -// Var(VarDecl), -// TsInterface(TsInterfaceDecl), -// TsTypeAlias(TsTypeAliasDecl), -// TsEnum(TsEnumDecl), -// TsModule(TsModuleDecl), -// } -// -// pub struct FnDecl { -// pub ident: Ident, -// -// pub declare: bool, -// -// pub function: Function, -// } -// -// pub struct ClassDecl { -// pub ident: Ident, -// -// pub declare: bool, -// -// pub class: Class, -// } -// -// pub struct VarDecl { -// pub span: Span, -// -// pub kind: VarDeclKind, -// -// pub declare: bool, -// -// pub decls: Vec, -// } -// -// pub enum VarDeclKind { -// Var, -// Let, -// Const, -// } -// -// pub struct VarDeclarator { -// pub span: Span, -// pub name: Pat, -// -// pub init: Option>, -// -// pub definite: bool, -// } -// -// pub enum Expr { -// This(ThisExpr), -// -// Array(ArrayLit), -// -// Object(ObjectLit), -// -// Fn(FnExpr), -// -// Unary(UnaryExpr), -// -// Update(UpdateExpr), -// -// Bin(BinExpr), -// -// Assign(AssignExpr), -// -// Member(MemberExpr), -// -// Cond(CondExpr), -// -// Call(CallExpr), -// -// New(NewExpr), -// -// Seq(SeqExpr), -// -// Ident(Ident), -// -// Lit(Lit), -// -// Tpl(Tpl), -// -// TaggedTpl(TaggedTpl), -// -// Arrow(ArrowExpr), -// -// Class(ClassExpr), -// -// Yield(YieldExpr), -// -// MetaProp(MetaPropExpr), -// -// Await(AwaitExpr), -// -// Paren(ParenExpr), -// -// JSXMember(JSXMemberExpr), -// -// JSXNamespacedName(JSXNamespacedName), -// -// JSXEmpty(JSXEmptyExpr), -// -// JSXElement(Box), -// -// JSXFragment(JSXFragment), -// -// TsTypeAssertion(TsTypeAssertion), -// -// TsConstAssertion(TsConstAssertion), -// -// TsNonNull(TsNonNullExpr), -// -// TsTypeCast(TsTypeCastExpr), -// -// TsAs(TsAsExpr), -// -// PrivateName(PrivateName), -// -// OptChain(OptChainExpr), -// -// Invalid(Invalid), -// } -// -// pub struct ThisExpr { -// pub span: Span, -// } -// -// pub struct ArrayLit { -// pub span: Span, -// -// pub elems: Vec>, -// } -// -// pub struct ObjectLit { -// pub span: Span, -// -// pub props: Vec, -// } -// -// pub enum PropOrSpread { -// Spread(SpreadElement), -// -// Prop(Box), -// } -// -// pub struct SpreadElement { -// pub dot3_token: Span, -// -// pub expr: Box, -// } -// -// pub struct UnaryExpr { -// pub span: Span, -// -// pub op: UnaryOp, -// -// pub arg: Box, -// } -// -// pub struct UpdateExpr { -// pub span: Span, -// -// pub op: UpdateOp, -// -// pub prefix: bool, -// -// pub arg: Box, -// } -// -// pub struct BinExpr { -// pub span: Span, -// -// pub op: BinaryOp, -// -// pub left: Box, -// -// pub right: Box, -// } -// -// pub struct FnExpr { -// pub ident: Option, -// -// pub function: Function, -// } -// -// pub struct ClassExpr { -// pub ident: Option, -// -// pub class: Class, -// } -// -// pub struct AssignExpr { -// pub span: Span, -// -// pub op: AssignOp, -// -// pub left: PatOrExpr, -// -// pub right: Box, -// } -// -// pub struct MemberExpr { -// pub span: Span, -// -// pub obj: ExprOrSuper, -// -// pub prop: Box, -// -// pub computed: bool, -// } -// -// pub struct CondExpr { -// pub span: Span, -// -// pub test: Box, -// -// pub cons: Box, -// -// pub alt: Box, -// } -// -// pub struct CallExpr { -// pub span: Span, -// -// pub callee: ExprOrSuper, -// -// pub args: Vec, -// -// pub type_args: Option, -// } -// -// pub struct NewExpr { -// pub span: Span, -// -// pub callee: Box, -// -// pub args: Option>, -// -// pub type_args: Option, -// } -// -// pub struct SeqExpr { -// pub span: Span, -// -// pub exprs: Vec>, -// } -// -// pub struct ArrowExpr { -// pub span: Span, -// -// pub params: Vec, -// -// pub body: BlockStmtOrExpr, -// -// pub is_async: bool, -// -// pub is_generator: bool, -// -// pub type_params: Option, -// -// pub return_type: Option, -// } -// -// pub struct YieldExpr { -// pub span: Span, -// -// pub arg: Option>, -// -// pub delegate: bool, -// } -// -// pub struct MetaPropExpr { -// pub meta: Ident, -// -// pub prop: Ident, -// } -// -// pub struct AwaitExpr { -// pub span: Span, -// -// pub arg: Box, -// } -// -// pub struct Tpl { -// pub span: Span, -// -// pub exprs: Vec>, -// -// pub quasis: Vec, -// } -// -// pub struct TaggedTpl { -// pub span: Span, -// -// pub tag: Box, -// -// pub exprs: Vec>, -// pub quasis: Vec, -// -// pub type_params: Option, -// } -// -// pub struct TplElement { -// pub span: Span, -// pub tail: bool, -// pub cooked: Option, -// pub raw: Str, -// } -// -// pub struct ParenExpr { -// pub span: Span, -// -// pub expr: Box, -// } -// -// pub enum ExprOrSuper { -// Super(Super), -// -// Expr(Box), -// } -// -// pub struct Super { -// pub span: Span, -// } -// -// pub struct ExprOrSpread { -// pub spread: Option, -// -// pub expr: Box, -// } -// -// pub enum BlockStmtOrExpr { -// BlockStmt(BlockStmt), -// Expr(Box), -// } -// -// pub enum PatOrExpr { -// Expr(Box), -// Pat(Box), -// } -// -// pub struct OptChainExpr { -// pub span: Span, -// pub expr: Box, -// } -// -// pub struct Function { -// pub params: Vec, -// -// pub decorators: Vec, -// -// pub span: Span, -// -// pub body: Option, -// -// pub is_generator: bool, -// -// pub is_async: bool, -// -// pub type_params: Option, -// -// pub return_type: Option, -// } -// -// pub enum PatOrTsParamProp { -// TsParamProp(TsParamProp), -// Pat(Pat), -// } -// -// pub struct Ident { -// pub span: Span, -// pub sym: JsWord, -// pub type_ann: Option, -// pub optional: bool, -// } -// -// pub struct PrivateName { -// pub span: Span, -// pub id: Ident, -// } -// -// pub enum JSXObject { -// JSXMemberExpr(Box), -// Ident(Ident), -// } -// -// pub struct JSXMemberExpr { -// pub obj: JSXObject, -// -// pub prop: Ident, -// } -// -// pub struct JSXNamespacedName { -// pub ns: Ident, -// pub name: Ident, -// } -// -// pub struct JSXEmptyExpr { -// pub span: Span, -// } -// -// pub struct JSXExprContainer { -// pub span: Span, -// pub expr: JSXExpr, -// } -// -// pub enum JSXExpr { -// JSXEmptyExpr(JSXEmptyExpr), -// Expr(Box), -// } -// -// pub struct JSXSpreadChild { -// pub span: Span, -// pub expr: Box, -// } -// -// pub enum JSXElementName { -// Ident(Ident), -// JSXMemberExpr(JSXMemberExpr), -// JSXNamespacedName(JSXNamespacedName), -// } -// -// pub struct JSXOpeningElement { -// pub name: JSXElementName, -// -// pub span: Span, -// -// pub attrs: Vec, -// -// pub self_closing: bool, -// -// pub type_args: Option, -// } -// -// pub enum JSXAttrOrSpread { -// JSXAttr(JSXAttr), -// SpreadElement(SpreadElement), -// } -// -// pub struct JSXClosingElement { -// pub span: Span, -// pub name: JSXElementName, -// } -// -// pub struct JSXAttr { -// pub span: Span, -// pub name: JSXAttrName, -// pub value: Option, -// } -// -// pub enum JSXAttrName { -// Ident(Ident), -// JSXNamespacedName(JSXNamespacedName), -// } -// -// pub enum JSXAttrValue { -// Lit(Lit), -// -// JSXExprContainer(JSXExprContainer), -// -// JSXElement(Box), -// -// JSXFragment(JSXFragment), -// } -// -// pub struct JSXText { -// pub span: Span, -// pub value: JsWord, -// pub raw: JsWord, -// } -// -// pub struct JSXElement { -// pub span: Span, -// pub opening: JSXOpeningElement, -// pub children: Vec, -// pub closing: Option, -// } -// -// pub enum JSXElementChild { -// JSXText(JSXText), -// -// JSXExprContainer(JSXExprContainer), -// -// JSXSpreadChild(JSXSpreadChild), -// -// JSXElement(Box), -// -// JSXFragment(JSXFragment), -// } -// -// pub struct JSXFragment { -// pub span: Span, -// -// pub opening: JSXOpeningFragment, -// -// pub children: Vec, -// -// pub closing: JSXClosingFragment, -// } -// -// pub struct JSXOpeningFragment { -// pub span: Span, -// } -// -// pub struct JSXClosingFragment { -// pub span: Span, -// } -// -// pub struct Invalid { -// pub span: Span, -// } -// -// pub enum Lit { -// Str(Str), -// -// Bool(Bool), -// -// Null(Null), -// -// Num(Number), -// -// BigInt(BigInt), -// -// Regex(Regex), -// -// JSXText(JSXText), -// } -// -// pub struct BigInt { -// pub span: Span, -// pub value: BigIntValue, -// } -// -// pub struct Str { -// pub span: Span, -// -// pub value: JsWord, -// -// pub has_escape: bool, -// } -// -// pub struct Bool { -// pub span: Span, -// pub value: bool, -// } -// -// pub struct Null { -// pub span: Span, -// } -// -// pub struct Regex { -// pub span: Span, -// -// pub exp: JsWord, -// -// pub flags: JsWord, -// } -// -// pub struct Number { -// pub span: Span, -// pub value: f64, -// } -// -// pub enum Program { -// Module(Module), -// Script(Script), -// } -// -// pub struct Module { -// pub span: Span, -// -// pub body: Vec, -// -// pub shebang: Option, -// } -// -// pub struct Script { -// pub span: Span, -// -// pub body: Vec, -// -// pub shebang: Option, -// } -// -// pub enum ModuleItem { -// ModuleDecl(ModuleDecl), -// Stmt(Stmt), -// } -// -// pub enum ModuleDecl { -// Import(ImportDecl), -// -// ExportDecl(ExportDecl), -// -// ExportNamed(NamedExport), -// -// ExportDefaultDecl(ExportDefaultDecl), -// -// ExportDefaultExpr(ExportDefaultExpr), -// -// ExportAll(ExportAll), -// -// TsImportEquals(TsImportEqualsDecl), -// -// TsExportAssignment(TsExportAssignment), -// -// TsNamespaceExport(TsNamespaceExportDecl), -// } -// -// pub struct ExportDefaultExpr { -// pub span: Span, -// -// pub expr: Box, -// } -// -// pub struct ExportDecl { -// pub span: Span, -// -// pub decl: Decl, -// } -// -// pub struct ImportDecl { -// pub span: Span, -// -// pub specifiers: Vec, -// -// pub src: Str, -// -// pub type_only: bool, -// } -// -// pub struct ExportAll { -// pub span: Span, -// -// pub src: Str, -// } -// -// pub struct NamedExport { -// pub span: Span, -// -// pub specifiers: Vec, -// -// pub src: Option, -// -// pub type_only: bool, -// } -// -// pub struct ExportDefaultDecl { -// pub span: Span, -// -// pub decl: DefaultDecl, -// } -// -// pub enum DefaultDecl { -// Class(ClassExpr), -// -// Fn(FnExpr), -// -// TsInterfaceDecl(TsInterfaceDecl), -// } -// -// pub enum ImportSpecifier { -// Specific(ImportSpecific), -// Default(ImportDefault), -// Namespace(ImportStarAs), -// } -// -// pub struct ImportDefault { -// pub span: Span, -// -// pub local: Ident, -// } -// pub struct ImportStarAs { -// pub span: Span, -// -// pub local: Ident, -// } -// pub struct ImportSpecific { -// pub span: Span, -// -// pub local: Ident, -// -// pub imported: Option, -// } -// -// pub enum ExportSpecifier { -// Namespace(NamespaceExportSpecifier), -// -// Default(DefaultExportSpecifier), -// -// Named(NamedExportSpecifier), -// } -// -// pub struct NamespaceExportSpecifier { -// pub span: Span, -// -// pub name: Ident, -// } -// -// pub struct DefaultExportSpecifier { -// pub exported: Ident, -// } -// -// pub struct NamedExportSpecifier { -// pub span: Span, -// pub orig: Ident, -// pub exported: Option, -// } -// -// pub enum BinaryOp { -// EqEq, -// NotEq, -// EqEqEq, -// NotEqEq, -// Lt, -// LtEq, -// Gt, -// GtEq, -// LShift, -// RShift, -// ZeroFillRShift, -// -// Add, -// Sub, -// Mul, -// Div, -// Mod, -// -// BitOr, -// BitXor, -// BitAnd, -// -// LogicalOr, -// -// LogicalAnd, -// -// In, -// InstanceOf, -// -// Exp, -// -// NullishCoalescing, -// } -// -// pub enum AssignOp { -// Assign, -// AddAssign, -// SubAssign, -// MulAssign, -// DivAssign, -// ModAssign, -// LShiftAssign, -// RShiftAssign, -// ZeroFillRShiftAssign, -// BitOrAssign, -// BitXorAssign, -// BitAndAssign, -// -// ExpAssign, -// } -// -// pub enum UpdateOp { -// PlusPlus, -// MinusMinus, -// } -// -// pub enum UnaryOp { -// Minus, -// Plus, -// Bang, -// Tilde, -// TypeOf, -// Void, -// Delete, -// } -// -// pub enum Pat { -// Ident(Ident), -// -// Array(ArrayPat), -// -// Rest(RestPat), -// -// Object(ObjectPat), -// -// Assign(AssignPat), -// -// Invalid(Invalid), -// -// Expr(Box), -// } -// -// pub struct ArrayPat { -// pub span: Span, -// -// pub elems: Vec>, -// -// pub optional: bool, -// -// pub type_ann: Option, -// } -// -// pub struct ObjectPat { -// pub span: Span, -// -// pub props: Vec, -// -// pub optional: bool, -// -// pub type_ann: Option, -// } -// -// pub struct AssignPat { -// pub span: Span, -// -// pub left: Box, -// -// pub right: Box, -// -// pub type_ann: Option, -// } -// -// pub struct RestPat { -// pub span: Span, -// -// pub dot3_token: Span, -// -// pub arg: Box, -// -// pub type_ann: Option, -// } -// -// pub enum ObjectPatProp { -// KeyValue(KeyValuePatProp), -// -// Assign(AssignPatProp), -// -// Rest(RestPat), -// } -// -// pub struct KeyValuePatProp { -// pub key: PropName, -// -// pub value: Box, -// } -// pub struct AssignPatProp { -// pub span: Span, -// pub key: Ident, -// -// pub value: Option>, -// } -// -// pub enum Prop { -// Shorthand(Ident), -// -// KeyValue(KeyValueProp), -// -// Assign(AssignProp), -// -// Getter(GetterProp), -// -// Setter(SetterProp), -// -// Method(MethodProp), -// } -// -// pub struct KeyValueProp { -// pub key: PropName, -// -// pub value: Box, -// } -// -// pub struct AssignProp { -// pub key: Ident, -// pub value: Box, -// } -// -// pub struct GetterProp { -// pub span: Span, -// pub key: PropName, -// pub type_ann: Option, -// pub body: Option, -// } -// pub struct SetterProp { -// pub span: Span, -// pub key: PropName, -// pub param: Pat, -// pub body: Option, -// } -// pub struct MethodProp { -// pub key: PropName, -// -// pub function: Function, -// } -// -// pub enum PropName { -// Ident(Ident), -// Str(Str), -// Num(Number), -// Computed(ComputedPropName), -// } -// -// pub struct ComputedPropName { -// pub span: Span, -// pub expr: Box, -// } -// use crate::{ -// decl::{Decl, VarDecl}, -// expr::Expr, -// ident::Ident, -// pat::Pat, -// }; -// -// pub struct BlockStmt { -// pub span: Span, -// -// pub stmts: Vec, -// } -// -// pub enum Stmt { -// Block(BlockStmt), -// -// Empty(EmptyStmt), -// -// Debugger(DebuggerStmt), -// -// With(WithStmt), -// -// Return(ReturnStmt), -// -// Labeled(LabeledStmt), -// -// Break(BreakStmt), -// -// Continue(ContinueStmt), -// -// If(IfStmt), -// -// Switch(SwitchStmt), -// -// Throw(ThrowStmt), -// -// Try(TryStmt), -// -// While(WhileStmt), -// -// DoWhile(DoWhileStmt), -// -// For(ForStmt), -// -// ForIn(ForInStmt), -// -// ForOf(ForOfStmt), -// -// Decl(Decl), -// -// Expr(ExprStmt), -// } -// -// pub struct ExprStmt { -// pub span: Span, -// pub expr: Box, -// } -// -// pub struct EmptyStmt { -// pub span: Span, -// } -// -// pub struct DebuggerStmt { -// pub span: Span, -// } -// -// pub struct WithStmt { -// pub span: Span, -// pub obj: Box, -// pub body: Box, -// } -// -// pub struct ReturnStmt { -// pub span: Span, -// pub arg: Option>, -// } -// -// pub struct LabeledStmt { -// pub span: Span, -// pub label: Ident, -// pub body: Box, -// } -// -// pub struct BreakStmt { -// pub span: Span, -// pub label: Option, -// } -// -// pub struct ContinueStmt { -// pub span: Span, -// pub label: Option, -// } -// -// pub struct IfStmt { -// pub span: Span, -// pub test: Box, -// -// pub cons: Box, -// -// pub alt: Option>, -// } -// -// pub struct SwitchStmt { -// pub span: Span, -// pub discriminant: Box, -// pub cases: Vec, -// } -// -// pub struct ThrowStmt { -// pub span: Span, -// pub arg: Box, -// } -// -// pub struct TryStmt { -// pub span: Span, -// -// pub block: BlockStmt, -// -// pub handler: Option, -// -// pub finalizer: Option, -// } -// -// pub struct WhileStmt { -// pub span: Span, -// pub test: Box, -// pub body: Box, -// } -// -// pub struct DoWhileStmt { -// pub span: Span, -// pub test: Box, -// pub body: Box, -// } -// -// pub struct ForStmt { -// pub span: Span, -// -// pub init: Option, -// -// pub test: Option>, -// -// pub update: Option>, -// -// pub body: Box, -// } -// -// pub struct ForInStmt { -// pub span: Span, -// pub left: VarDeclOrPat, -// pub right: Box, -// pub body: Box, -// } -// -// pub struct ForOfStmt { -// pub span: Span, -// pub await_token: Option, -// pub left: VarDeclOrPat, -// pub right: Box, -// pub body: Box, -// } -// -// pub struct SwitchCase { -// pub span: Span, -// -// pub test: Option>, -// -// pub cons: Vec, -// } -// -// pub struct CatchClause { -// pub span: Span, -// pub param: Option, -// -// pub body: BlockStmt, -// } -// -// pub enum VarDeclOrPat { -// VarDecl(VarDecl), -// -// Pat(Pat), -// } -// -// pub enum VarDeclOrExpr { -// VarDecl(VarDecl), -// -// Expr(Box), -// } -// -// pub struct TsTypeAnn { -// pub span: Span, -// pub type_ann: Box, -// } -// -// pub struct TsTypeParamDecl { -// pub span: Span, -// pub params: Vec, -// } -// -// pub struct TsTypeParam { -// pub span: Span, -// pub name: Ident, -// -// pub constraint: Option>, -// -// pub default: Option>, -// } -// -// pub struct TsTypeParamInstantiation { -// pub span: Span, -// pub params: Vec>, -// } -// -// pub struct TsTypeCastExpr { -// pub span: Span, -// pub expr: Box, -// pub type_ann: TsTypeAnn, -// } -// -// pub struct TsParamProp { -// pub span: Span, -// pub decorators: Vec, -// pub accessibility: Option, -// pub readonly: bool, -// pub param: TsParamPropParam, -// } -// -// pub enum TsParamPropParam { -// Ident(Ident), -// -// Assign(AssignPat), -// } -// -// pub struct TsQualifiedName { -// pub left: TsEntityName, -// pub right: Ident, -// } -// -// pub enum TsEntityName { -// TsQualifiedName(Box), -// -// Ident(Ident), -// } -// -// pub enum TsSignatureDecl { -// TsCallSignatureDecl(TsCallSignatureDecl), -// -// TsConstructSignatureDecl(TsConstructSignatureDecl), -// -// TsMethodSignature(TsMethodSignature), -// -// TsFnType(TsFnType), -// -// TsConstructorType(TsConstructorType), -// } -// -// pub enum TsTypeElement { -// TsCallSignatureDecl(TsCallSignatureDecl), -// -// TsConstructSignatureDecl(TsConstructSignatureDecl), -// -// TsPropertySignature(TsPropertySignature), -// -// TsMethodSignature(TsMethodSignature), -// -// TsIndexSignature(TsIndexSignature), -// } -// -// pub struct TsCallSignatureDecl { -// pub span: Span, -// pub params: Vec, -// pub type_ann: Option, -// pub type_params: Option, -// } -// -// pub struct TsConstructSignatureDecl { -// pub span: Span, -// pub params: Vec, -// pub type_ann: Option, -// pub type_params: Option, -// } -// -// pub struct TsPropertySignature { -// pub span: Span, -// pub readonly: bool, -// pub key: Box, -// pub computed: bool, -// pub optional: bool, -// pub init: Option>, -// pub params: Vec, -// pub type_ann: Option, -// pub type_params: Option, -// } -// -// pub struct TsMethodSignature { -// pub span: Span, -// pub readonly: bool, -// pub key: Box, -// pub computed: bool, -// pub optional: bool, -// pub params: Vec, -// pub type_ann: Option, -// pub type_params: Option, -// } -// -// pub struct TsIndexSignature { -// pub params: Vec, -// pub type_ann: Option, -// -// pub readonly: bool, -// pub span: Span, -// } -// -// pub enum TsType { -// TsKeywordType(TsKeywordType), -// -// TsThisType(TsThisType), -// -// TsFnOrConstructorType(TsFnOrConstructorType), -// -// TsTypeRef(TsTypeRef), -// -// TsTypeQuery(TsTypeQuery), -// -// TsTypeLit(TsTypeLit), -// -// TsArrayType(TsArrayType), -// -// TsTupleType(TsTupleType), -// -// TsOptionalType(TsOptionalType), -// -// TsRestType(TsRestType), -// -// TsUnionOrIntersectionType(TsUnionOrIntersectionType), -// -// TsConditionalType(TsConditionalType), -// -// TsInferType(TsInferType), -// -// TsParenthesizedType(TsParenthesizedType), -// -// TsTypeOperator(TsTypeOperator), -// -// TsIndexedAccessType(TsIndexedAccessType), -// -// TsMappedType(TsMappedType), -// -// TsLitType(TsLitType), -// -// TsTypePredicate(TsTypePredicate), -// -// TsImportType(TsImportType), -// } -// -// pub enum TsFnOrConstructorType { -// TsFnType(TsFnType), -// TsConstructorType(TsConstructorType), -// } -// -// pub struct TsKeywordType { -// pub span: Span, -// pub kind: TsKeywordTypeKind, -// } -// -// pub enum TsKeywordTypeKind { -// TsAnyKeyword, -// -// TsUnknownKeyword, -// -// TsNumberKeyword, -// -// TsObjectKeyword, -// -// TsBooleanKeyword, -// -// TsBigIntKeyword, -// -// TsStringKeyword, -// -// TsSymbolKeyword, -// -// TsVoidKeyword, -// -// TsUndefinedKeyword, -// -// TsNullKeyword, -// -// TsNeverKeyword, -// } -// -// pub struct TsThisType { -// pub span: Span, -// } -// -// pub enum TsFnParam { -// Ident(Ident), -// -// Array(ArrayPat), -// -// Rest(RestPat), -// -// Object(ObjectPat), -// } -// -// pub struct TsFnType { -// pub span: Span, -// pub params: Vec, -// -// pub type_params: Option, -// pub type_ann: TsTypeAnn, -// } -// -// pub struct TsConstructorType { -// pub span: Span, -// pub params: Vec, -// pub type_params: Option, -// pub type_ann: TsTypeAnn, -// } -// -// pub struct TsTypeRef { -// pub span: Span, -// pub type_name: TsEntityName, -// pub type_params: Option, -// } -// -// pub struct TsTypePredicate { -// pub span: Span, -// pub asserts: bool, -// pub param_name: TsThisTypeOrIdent, -// pub type_ann: Option, -// } -// -// pub enum TsThisTypeOrIdent { -// TsThisType(TsThisType), -// -// Ident(Ident), -// } -// -// pub struct TsTypeQuery { -// pub span: Span, -// pub expr_name: TsTypeQueryExpr, -// } -// -// pub enum TsTypeQueryExpr { -// TsEntityName(TsEntityName), -// Import(TsImportType), -// } -// -// pub struct TsImportType { -// pub span: Span, -// pub arg: Str, -// pub qualifier: Option, -// pub type_args: Option, -// } -// -// pub struct TsTypeLit { -// pub span: Span, -// pub members: Vec, -// } -// -// pub struct TsArrayType { -// pub span: Span, -// pub elem_type: Box, -// } -// -// pub struct TsTupleType { -// pub span: Span, -// pub elem_types: Vec>, -// } -// -// pub struct TsOptionalType { -// pub span: Span, -// pub type_ann: Box, -// } -// -// pub struct TsRestType { -// pub span: Span, -// pub type_ann: Box, -// } -// -// pub enum TsUnionOrIntersectionType { -// TsUnionType(TsUnionType), -// -// TsIntersectionType(TsIntersectionType), -// } -// -// pub struct TsUnionType { -// pub span: Span, -// pub types: Vec>, -// } -// -// pub struct TsIntersectionType { -// pub span: Span, -// pub types: Vec>, -// } -// -// pub struct TsConditionalType { -// pub span: Span, -// pub check_type: Box, -// pub extends_type: Box, -// pub true_type: Box, -// pub false_type: Box, -// } -// -// pub struct TsInferType { -// pub span: Span, -// pub type_param: TsTypeParam, -// } -// -// pub struct TsParenthesizedType { -// pub span: Span, -// pub type_ann: Box, -// } -// -// pub struct TsTypeOperator { -// pub span: Span, -// pub op: TsTypeOperatorOp, -// pub type_ann: Box, -// } -// -// pub enum TsTypeOperatorOp { -// KeyOf, -// Unique, -// ReadOnly, -// } -// -// pub struct TsIndexedAccessType { -// pub span: Span, -// pub readonly: bool, -// pub obj_type: Box, -// pub index_type: Box, -// } -// -// pub enum TruePlusMinus { -// True, -// Plus, -// Minus, -// } -// -// pub struct TsMappedType { -// pub span: Span, -// pub readonly: Option, -// pub type_param: TsTypeParam, -// pub optional: Option, -// pub type_ann: Option>, -// } -// -// pub struct TsLitType { -// pub span: Span, -// pub lit: TsLit, -// } -// -// pub enum TsLit { -// Number(Number), -// -// Str(Str), -// -// Bool(Bool), -// } -// -// pub struct TsInterfaceDecl { -// pub span: Span, -// pub id: Ident, -// pub declare: bool, -// pub type_params: Option, -// pub extends: Vec, -// pub body: TsInterfaceBody, -// } -// -// pub struct TsInterfaceBody { -// pub span: Span, -// pub body: Vec, -// } -// -// pub struct TsExprWithTypeArgs { -// pub span: Span, -// pub expr: TsEntityName, -// pub type_args: Option, -// } -// -// pub struct TsTypeAliasDecl { -// pub span: Span, -// pub declare: bool, -// pub id: Ident, -// pub type_params: Option, -// pub type_ann: Box, -// } -// -// pub struct TsEnumDecl { -// pub span: Span, -// pub declare: bool, -// pub is_const: bool, -// pub id: Ident, -// pub members: Vec, -// } -// -// pub struct TsEnumMember { -// pub span: Span, -// pub id: TsEnumMemberId, -// pub init: Option>, -// } -// -// pub enum TsEnumMemberId { -// Ident(Ident), -// -// Str(Str), -// } -// -// pub struct TsModuleDecl { -// pub span: Span, -// pub declare: bool, -// pub global: bool, -// pub id: TsModuleName, -// pub body: Option, -// } -// -// pub enum TsNamespaceBody { -// TsModuleBlock(TsModuleBlock), -// -// TsNamespaceDecl(TsNamespaceDecl), -// } -// -// pub struct TsModuleBlock { -// pub span: Span, -// pub body: Vec, -// } -// -// pub struct TsNamespaceDecl { -// pub span: Span, -// pub declare: bool, -// pub global: bool, -// pub id: Ident, -// pub body: Box, -// } -// -// pub enum TsModuleName { -// Ident(Ident), -// -// Str(Str), -// } -// -// pub struct TsImportEqualsDecl { -// pub span: Span, -// pub declare: bool, -// pub is_export: bool, -// pub id: Ident, -// pub module_ref: TsModuleRef, -// } -// -// pub enum TsModuleRef { -// TsEntityName(TsEntityName), -// -// TsExternalModuleRef(TsExternalModuleRef), -// } -// -// pub struct TsExternalModuleRef { -// pub span: Span, -// pub expr: Str, -// } -// -// pub struct TsExportAssignment { -// pub span: Span, -// pub expr: Box, -// } -// -// pub struct TsNamespaceExportDecl { -// pub span: Span, -// pub id: Ident, -// } -// -// pub struct TsAsExpr { -// pub span: Span, -// pub expr: Box, -// pub type_ann: Box, -// } -// -// pub struct TsTypeAssertion { -// pub span: Span, -// pub expr: Box, -// pub type_ann: Box, -// } -// -// pub struct TsNonNullExpr { -// pub span: Span, -// pub expr: Box, -// } -// -// pub enum Accessibility { -// Public, -// Protected, -// Private, -// } -// -// pub struct TsConstAssertion { -// pub span: Span, -// pub expr: Box, -// } -// } From d28066f93b01136f392dba47def3ae4ac56b5318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:15:45 +0900 Subject: [PATCH 19/32] Skip primitives --- ecmascript/visit/Cargo.toml | 2 + ecmascript/visit/macros/src/lib.rs | 318 ++++++++++++++++------------- ecmascript/visit/src/lib.rs | 4 +- 3 files changed, 186 insertions(+), 138 deletions(-) diff --git a/ecmascript/visit/Cargo.toml b/ecmascript/visit/Cargo.toml index 6f0979dad0f9..edd144cf22ca 100644 --- a/ecmascript/visit/Cargo.toml +++ b/ecmascript/visit/Cargo.toml @@ -10,6 +10,8 @@ edition = "2018" [dependencies] +swc_atoms = { version = "0.2", path = "../../atoms" } swc_common = { version = "0.5.9", path = "../../common" } swc_ecma_ast = { version = "0.18.0", path ="../ast" } swc_ecma_visit_macros = { version = "0.1.0", path ="./macros" } +num-bigint = { version = "0.2", features = ["serde"] } diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index d5e2f2a440bb..0359529430ba 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -1,9 +1,9 @@ use inflector::Inflector; -use pmutil::{q, smart_quote, IdentExt, ToTokensExt}; +use pmutil::{q, IdentExt}; use proc_macro2::Ident; use swc_macros_common::{call_site, def_site}; use syn::{ - parse::{Parse, ParseBuffer, ParseStream}, + parse::{ParseBuffer, ParseStream}, parse_quote::parse, punctuated::Punctuated, spanned::Spanned, @@ -11,7 +11,8 @@ use syn::{ Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, FieldPat, FieldValue, Fields, GenericArgument, ImplItem, ImplItemMethod, Index, Item, ItemEnum, ItemImpl, ItemMod, ItemStruct, ItemTrait, Member, Pat, PatStruct, Path, PathArguments, ReturnType, Signature, - Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, Type, Variant, VisPublic, Visibility, + Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, Type, TypePath, Variant, VisPublic, + Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -96,7 +97,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { let block: Block = parse(tts.into()); // Required to generate specialization code. - let mut type_names = vec![]; + let mut types = vec![]; let mut methods = vec![]; for stmts in block.stmts { @@ -105,12 +106,27 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { _ => unimplemented!("error reporting for something other than Item"), }; - let mtd = make_method(item, &mut type_names); - methods.push(TraitItem::Method(mtd)); + let mtd = make_method(item, &mut types); + methods.push(mtd); } let mut tokens = q!({}); + for ty in types { + let name = method_name(&ty); + let s = name.to_string(); + if methods.iter().any(|m| m.sig.ident == &*s) { + continue; + } + + methods.push(TraitItemMethod { + attrs: vec![], + sig: create_method_sig(&ty), + default: None, + semi_token: None, + }); + } + tokens.push_tokens(&ItemTrait { attrs: vec![], vis: Visibility::Public(VisPublic { @@ -124,7 +140,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { colon_token: None, supertraits: Default::default(), brace_token: def_site(), - items: methods, + items: methods.into_iter().map(TraitItem::Method).collect(), }); tokens.into() @@ -136,6 +152,9 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { for (i, field) in variant.iter().enumerate() { let ty = &field.ty; + if skip(ty) { + continue; + } let visit_name = method_name(&ty); let binding_ident = field .ident @@ -196,99 +215,49 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { } } -// fn make_arm_from_call(e: Option<&ItemEnum>, variant: &ExprCall) -> Arm { -// let mut stmts = vec![]; -// let mut bindings: Punctuated<_, Token![,]> = Default::default(); -// -// for (i, ty) in variant.args.iter().enumerate() { -// let ty = match ty { -// Expr::Path(ty) => ty.path.segments.last().unwrap().ident.clone(), -// _ => unimplemented!("proper error reporting for non-path -// expressions is tuple structs"), }; -// let field_name = Ident::new(&format!("_{}", i), ty.span()); -// let visit_name = ty.new_ident_with(method_name); -// let stmt = q!( -// Vars { -// field_name: &field_name, -// visit_name, -// }, -// { -// self.visit_name(field_name, n as _); -// } -// ) -// .parse(); -// stmts.push(stmt); -// -// bindings.push(field_name.clone()); -// } -// -// let block = Block { -// brace_token: def_site(), -// stmts, -// }; -// -// Arm { -// attrs: vec![], -// pat: match e { -// Some(e) => q!( -// Vars { -// Enum: e, -// Variant: &variant.func, -// bindings, -// }, -// { Enum::Variant(bindings) } -// ) -// .parse(), -// None => q!( -// Vars { -// Variant: &variant.func, -// bindings, -// }, -// { Variant(bindings) } -// ) -// .parse(), -// }, -// guard: None, -// fat_arrow_token: def_site(), -// body: Box::new(Expr::Block(ExprBlock { -// attrs: vec![], -// label: None, -// block, -// })), -// comma: None, -// } -// } - -fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { - fn method_sig(type_name: &Ident) -> Signature { - Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: def_site(), - ident: type_name.clone().new_ident_with(prefix_method_name), - generics: Default::default(), - paren_token: def_site(), - inputs: { - let mut p = Punctuated::default(); - p.push_value(q!(Vars {}, { &self }).parse()); - p.push_punct(def_site()); - p.push_value(q!(Vars { Type: type_name }, { n: &Type }).parse()); - p.push_punct(def_site()); - p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); - - p - }, - variadic: None, - output: ReturnType::Default, - } +fn method_sig(ty: &Type) -> Signature { + Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: def_site(), + ident: method_name(ty), + generics: Default::default(), + paren_token: def_site(), + inputs: { + let mut p = Punctuated::default(); + p.push_value(q!(Vars {}, { &self }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars { Type: ty }, { n: &Type }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); + + p + }, + variadic: None, + output: ReturnType::Default, } +} +fn method_sig_from_ident(v: &Ident) -> Signature { + method_sig(&Type::Path(TypePath { + qself: None, + path: v.clone().into(), + })) +} + +fn make_method(e: Item, types: &mut Vec) -> TraitItemMethod { match e { Item::Struct(s) => { let type_name = &s.ident; - type_names.push(type_name.clone()); + types.push(Type::Path(TypePath { + qself: None, + path: type_name.clone().into(), + })); + for f in &s.fields { + types.push(f.ty.clone()); + } let block = { let arm = make_arm_from_struct(&s.ident.clone().into(), &s.fields); @@ -304,7 +273,7 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { TraitItemMethod { attrs: vec![], - sig: method_sig(type_name), + sig: method_sig_from_ident(type_name), default: Some(block), semi_token: None, } @@ -312,13 +281,24 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { Item::Enum(e) => { // let type_name = &e.ident; - type_names.push(e.ident.clone()); + types.push( + TypePath { + qself: None, + path: e.ident.clone().into(), + } + .into(), + ); + // let block = { let mut arms = vec![]; for variant in &e.variants { + for f in &variant.fields { + types.push(f.ty.clone()); + } + let arm = make_arm_from_struct( &q!( Vars { @@ -347,7 +327,7 @@ fn make_method(e: Item, type_names: &mut Vec) -> TraitItemMethod { TraitItemMethod { attrs: vec![], - sig: method_sig(type_name), + sig: method_sig_from_ident(type_name), default: Some(block), semi_token: None, } @@ -365,7 +345,36 @@ fn prefix_method_name(v: &str) -> String { } fn method_name(v: &Type) -> Ident { - match v { + create_method_sig(v).ident +} + +fn create_method_sig(ty: &Type) -> Signature { + fn mk(ident: Ident, ty: &Type) -> Signature { + Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: def_site(), + ident, + generics: Default::default(), + paren_token: def_site(), + inputs: { + let mut p = Punctuated::default(); + p.push_value(q!(Vars {}, { &self }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars { Type: ty }, { n: &Type }).parse()); + p.push_punct(def_site()); + p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); + + p + }, + variadic: None, + output: ReturnType::Default, + } + } + + match ty { Type::Array(_) => unimplemented!("type: array type"), Type::BareFn(_) => unimplemented!("type: fn type"), Type::Group(_) => unimplemented!("type: group type"), @@ -373,73 +382,108 @@ fn method_name(v: &Type) -> Ident { Type::Infer(_) => unreachable!("infer type"), Type::Macro(_) => unimplemented!("type: macro"), Type::Never(_) => unreachable!("never type"), - Type::Paren(ty) => return method_name(&ty.elem), + Type::Paren(ty) => return create_method_sig(&ty.elem), Type::Path(p) => { let last = p.path.segments.last().unwrap(); let ident = last.ident.new_ident_with(prefix_method_name); - if last.arguments.is_empty() { - return ident; - } - - if last.ident == "Box" { - match &last.arguments { - PathArguments::AngleBracketed(tps) => { - let arg = tps.args.first().unwrap(); + if !last.arguments.is_empty() { + if last.ident == "Box" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); - match arg { - GenericArgument::Type(ty) => return method_name(ty), - _ => unimplemented!("generic parameter other than type"), + match arg { + GenericArgument::Type(ty) => return create_method_sig(ty), + _ => unimplemented!("generic parameter other than type"), + } } + _ => unimplemented!("Box() -> T or Box without a type parameter"), } - _ => unimplemented!("Box() -> T or Box without a type parameter"), } - } - if last.ident == "Option" { - match &last.arguments { - PathArguments::AngleBracketed(tps) => { - let arg = tps.args.first().unwrap(); + if last.ident == "Option" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => { + let ident = method_name(arg) + .new_ident_with(|v| v.replace("visit_", "visit_opt_")); - match arg { - GenericArgument::Type(ty) => { - let i = method_name(ty); - return i.new_ident_with(|v| v.replace("visit_", "visit_opt_")); + return mk(ident, ty); + } + _ => unimplemented!("generic parameter other than type"), } - _ => unimplemented!("generic parameter other than type"), } + _ => unimplemented!("Box() -> T or Box without a type parameter"), } - _ => unimplemented!("Box() -> T or Box without a type parameter"), } - } - if last.ident == "Vec" { - match &last.arguments { - PathArguments::AngleBracketed(tps) => { - let arg = tps.args.first().unwrap(); + if last.ident == "Vec" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => { + let ident = + method_name(arg).new_ident_with(|v| format!("{}s", v)); - match arg { - GenericArgument::Type(ty) => { - let i = method_name(ty); - return i.new_ident_with(|v| format!("{}s", v)); + return mk(ident, ty); + } + _ => unimplemented!("generic parameter other than type"), } - _ => unimplemented!("generic parameter other than type"), } + _ => unimplemented!("Vec() -> Ret or Vec without a type parameter"), } - _ => unimplemented!("Vec() -> Ret or Vec without a type parameter"), } } - return ident; + return mk(ident, ty); } Type::Ptr(_) => unimplemented!("type: pointer"), Type::Reference(ty) => { - return method_name(&ty.elem); + return create_method_sig(&ty.elem); } Type::Slice(_) => unimplemented!("type: slice"), Type::TraitObject(_) => unimplemented!("type: trait object"), Type::Tuple(_) => unimplemented!("type: trait tuple"), Type::Verbatim(_) => unimplemented!("type: verbatim"), - _ => unimplemented!("Unknown type: {:?}", v), + _ => unimplemented!("Unknown type: {:?}", ty), + } +} + +fn skip(ty: &Type) -> bool { + match ty { + Type::Path(p) => { + if !p.path.segments.last().unwrap().arguments.is_empty() { + return true; + } + let i = &p.path.segments.last().as_ref().unwrap().ident; + + if i == "bool" + || i == "u128" + || i == "u128" + || i == "u64" + || i == "u32" + || i == "u16" + || i == "u8" + || i == "isize" + || i == "i128" + || i == "i128" + || i == "i64" + || i == "i32" + || i == "i16" + || i == "i8" + || i == "isize" + { + return true; + } + + false + } + _ => false, } } diff --git a/ecmascript/visit/src/lib.rs b/ecmascript/visit/src/lib.rs index e88442c1fd59..c2607d3655db 100644 --- a/ecmascript/visit/src/lib.rs +++ b/ecmascript/visit/src/lib.rs @@ -1,5 +1,7 @@ +use num_bigint::BigInt as BigIntValue; use std::any::Any; -use swc_common::AstNode; +use swc_atoms::JsWord; +use swc_common::Span; use swc_ecma_ast::*; use swc_ecma_visit_macros::define; From c7a89d71d800d1920773cd8531302a2b0aaf844d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:17:00 +0900 Subject: [PATCH 20/32] skip properly --- ecmascript/visit/macros/src/lib.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 0359529430ba..4c348e050e90 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -152,26 +152,26 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { for (i, field) in variant.iter().enumerate() { let ty = &field.ty; - if skip(ty) { - continue; - } + let visit_name = method_name(&ty); let binding_ident = field .ident .clone() .unwrap_or_else(|| Ident::new(&format!("_{}", i), call_site())); - let stmt = q!( - Vars { - binding_ident: &binding_ident, - visit_name - }, - { - self.visit_name(binding_ident, n as _); - } - ) - .parse(); - stmts.push(stmt); + if !skip(ty) { + let stmt = q!( + Vars { + binding_ident: &binding_ident, + visit_name + }, + { + self.visit_name(binding_ident, n as _); + } + ) + .parse(); + stmts.push(stmt); + } if field.ident.is_some() { fields.push( From ccb994ab0272ba39cb8d032d5a0ce553c83c01a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:20:06 +0900 Subject: [PATCH 21/32] Ignore float --- ecmascript/visit/macros/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 4c348e050e90..e327da9d3a96 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -431,7 +431,7 @@ fn create_method_sig(ty: &Type) -> Signature { let ident = method_name(arg).new_ident_with(|v| format!("{}s", v)); - return mk(ident, ty); + return mk(ident, &q!(Vars { arg }, { arg }).parse()); } _ => unimplemented!("generic parameter other than type"), } @@ -478,6 +478,8 @@ fn skip(ty: &Type) -> bool { || i == "i16" || i == "i8" || i == "isize" + || i == "f64" + || i == "f32" { return true; } From a32942e829413abe73ce6126c66c85b1ed68a7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:22:52 +0900 Subject: [PATCH 22/32] sort --- ecmascript/visit/macros/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index e327da9d3a96..23bdc3161672 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -127,6 +127,8 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { }); } + methods.sort_by_cached_key(|v| v.sig.ident.to_string()); + tokens.push_tokens(&ItemTrait { attrs: vec![], vis: Visibility::Public(VisPublic { @@ -394,7 +396,10 @@ fn create_method_sig(ty: &Type) -> Signature { let arg = tps.args.first().unwrap(); match arg { - GenericArgument::Type(ty) => return create_method_sig(ty), + GenericArgument::Type(arg) => { + let ident = method_name(&arg); + return mk(ident, &q!(Vars { arg }, { arg }).parse()); + } _ => unimplemented!("generic parameter other than type"), } } From df8f0a7fda10d88e9639ba0ca2c6a92707b2b07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:35:32 +0900 Subject: [PATCH 23/32] Proper skip --- ecmascript/visit/macros/src/lib.rs | 117 +++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 23bdc3161672..459a5a18997c 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -3,16 +3,10 @@ use pmutil::{q, IdentExt}; use proc_macro2::Ident; use swc_macros_common::{call_site, def_site}; use syn::{ - parse::{ParseBuffer, ParseStream}, - parse_quote::parse, - punctuated::Punctuated, - spanned::Spanned, - token::Token, - Arm, Block, Error, Expr, ExprBlock, ExprCall, ExprMatch, ExprStruct, FieldPat, FieldValue, - Fields, GenericArgument, ImplItem, ImplItemMethod, Index, Item, ItemEnum, ItemImpl, ItemMod, - ItemStruct, ItemTrait, Member, Pat, PatStruct, Path, PathArguments, ReturnType, Signature, - Stmt, Token, TraitItem, TraitItemMacro, TraitItemMethod, Type, TypePath, Variant, VisPublic, - Visibility, + parse_quote::parse, punctuated::Punctuated, spanned::Spanned, Arm, Block, Expr, ExprBlock, + ExprMatch, FieldValue, Fields, GenericArgument, Index, Item, ItemTrait, Member, Path, + PathArguments, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMethod, Type, TypePath, + VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -122,7 +116,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { methods.push(TraitItemMethod { attrs: vec![], sig: create_method_sig(&ty), - default: None, + default: Some(create_method_body(&ty)), semi_token: None, }); } @@ -168,7 +162,7 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { visit_name }, { - self.visit_name(binding_ident, n as _); + self.visit_name(&*binding_ident, n as _); } ) .parse(); @@ -433,8 +427,7 @@ fn create_method_sig(ty: &Type) -> Signature { match arg { GenericArgument::Type(arg) => { - let ident = - method_name(arg).new_ident_with(|v| format!("{}s", v)); + let ident = method_name(arg).new_ident_with(|v| v.to_plural()); return mk(ident, &q!(Vars { arg }, { arg }).parse()); } @@ -460,11 +453,105 @@ fn create_method_sig(ty: &Type) -> Signature { } } +fn create_method_body(ty: &Type) -> Block { + match ty { + Type::Array(_) => unimplemented!("type: array type"), + Type::BareFn(_) => unimplemented!("type: fn type"), + Type::Group(_) => unimplemented!("type: group type"), + Type::ImplTrait(_) => unimplemented!("type: impl trait"), + Type::Infer(_) => unreachable!("infer type"), + Type::Macro(_) => unimplemented!("type: macro"), + Type::Never(_) => unreachable!("never type"), + Type::Paren(ty) => return create_method_body(&ty.elem), + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + + if !last.arguments.is_empty() { + if last.ident == "Box" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => { + return create_method_body(arg); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Box() -> T or Box without a type parameter"), + } + } + + if last.ident == "Option" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => { + let ident = method_name(arg); + + return q!( + Vars { ident }, + ({ + match n { + Some(n) => self.ident(n, _parent), + None => {} + } + }) + ) + .parse(); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Box() -> T or Box without a type parameter"), + } + } + + if last.ident == "Vec" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => { + let ident = method_name(arg); + + return q!( + Vars { ident }, + ({ n.iter().for_each(|v| { self.ident(v, _parent) }) }) + ) + .parse(); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Vec() -> Ret or Vec without a type parameter"), + } + } + } + + q!(({})).parse() + } + Type::Ptr(_) => unimplemented!("type: pointer"), + Type::Reference(ty) => { + return create_method_body(&ty.elem); + } + Type::Slice(_) => unimplemented!("type: slice"), + Type::TraitObject(_) => unimplemented!("type: trait object"), + Type::Tuple(_) => unimplemented!("type: trait tuple"), + Type::Verbatim(_) => unimplemented!("type: verbatim"), + _ => unimplemented!("Unknown type: {:?}", ty), + } +} + fn skip(ty: &Type) -> bool { match ty { Type::Path(p) => { if !p.path.segments.last().unwrap().arguments.is_empty() { - return true; + return false; } let i = &p.path.segments.last().as_ref().unwrap().ident; From 53ccb7d2b3f10cffa3f7e6c43dfe2c16bb10f55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:38:29 +0900 Subject: [PATCH 24/32] Fix pluralization --- ecmascript/visit/macros/src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 459a5a18997c..ce841d1feda2 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -427,9 +427,14 @@ fn create_method_sig(ty: &Type) -> Signature { match arg { GenericArgument::Type(arg) => { - let ident = method_name(arg).new_ident_with(|v| v.to_plural()); + let orig_name = method_name(arg); + let mut ident = orig_name.new_ident_with(|v| v.to_plural()); - return mk(ident, &q!(Vars { arg }, { arg }).parse()); + if orig_name == ident.to_string() { + ident = ident.new_ident_with(|v| format!("{}_vec", v)); + } + + return mk(ident, &q!(Vars { arg }, { [arg] }).parse()); } _ => unimplemented!("generic parameter other than type"), } From 8eceee2663e7130a3f9d1797ec7a4288879633c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:46:08 +0900 Subject: [PATCH 25/32] Fix for Option where T: unused --- ecmascript/visit/macros/src/lib.rs | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index ce841d1feda2..abc943b6cc3d 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -106,6 +106,14 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { let mut tokens = q!({}); + { + let mut new = vec![]; + for ty in &types { + add_required(&mut new, ty); + } + types.extend(new); + } + for ty in types { let name = method_name(&ty); let s = name.to_string(); @@ -552,6 +560,32 @@ fn create_method_body(ty: &Type) -> Block { } } +fn add_required(types: &mut Vec, ty: &Type) { + match ty { + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + + if !last.arguments.is_empty() { + if last.ident == "Option" || last.ident == "Vec" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + match arg { + GenericArgument::Type(arg) => { + types.push(arg.clone()); + } + _ => unimplemented!("generic parameter other than type"), + } + } + _ => unimplemented!("Box() -> T or Box without a type parameter"), + } + } + } + } + _ => {} + } +} + fn skip(ty: &Type) -> bool { match ty { Type::Path(p) => { From c499b92a234bfdfa932a442b301c5cd74f1779b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 21:49:42 +0900 Subject: [PATCH 26/32] dedup --- ecmascript/visit/macros/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index abc943b6cc3d..17a1a847944b 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -114,6 +114,9 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { types.extend(new); } + methods.dedup_by_key(|v| v.sig.ident.to_string()); + methods.sort_by_cached_key(|v| v.sig.ident.to_string()); + for ty in types { let name = method_name(&ty); let s = name.to_string(); From 8aecc36cb342a22c182f06ec54f68e8dd0ab43fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 22:48:54 +0900 Subject: [PATCH 27/32] WIP: Option> and Vec> --- ecmascript/visit/macros/src/lib.rs | 155 ++++++++++++++++++++++++++--- 1 file changed, 140 insertions(+), 15 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 17a1a847944b..aa1492cad9b3 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -6,7 +6,7 @@ use syn::{ parse_quote::parse, punctuated::Punctuated, spanned::Spanned, Arm, Block, Expr, ExprBlock, ExprMatch, FieldValue, Fields, GenericArgument, Index, Item, ItemTrait, Member, Path, PathArguments, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMethod, Type, TypePath, - VisPublic, Visibility, + TypeReference, VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -167,16 +167,37 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { .unwrap_or_else(|| Ident::new(&format!("_{}", i), call_site())); if !skip(ty) { - let stmt = q!( + let mut expr: Expr = q!( Vars { - binding_ident: &binding_ident, - visit_name + binding_ident: &binding_ident }, - { - self.visit_name(&*binding_ident, n as _); - } + { &*binding_ident } ) .parse(); + if is_option(&ty) { + expr = if is_opt_vec(ty) { + q!( + Vars { + binding_ident: &binding_ident + }, + { &binding_ident.as_ref().map(|v| &**v) } + ) + .parse() + } else { + q!( + Vars { + binding_ident: &binding_ident + }, + { binding_ident.as_ref() } + ) + .parse() + }; + } + + let stmt = q!(Vars { expr, visit_name }, { + self.visit_name(expr, n as _); + }) + .parse(); stmts.push(stmt); } @@ -356,7 +377,7 @@ fn method_name(v: &Type) -> Ident { } fn create_method_sig(ty: &Type) -> Signature { - fn mk(ident: Ident, ty: &Type) -> Signature { + fn mk_exact(ident: Ident, ty: &Type) -> Signature { Signature { constness: None, asyncness: None, @@ -370,7 +391,7 @@ fn create_method_sig(ty: &Type) -> Signature { let mut p = Punctuated::default(); p.push_value(q!(Vars {}, { &self }).parse()); p.push_punct(def_site()); - p.push_value(q!(Vars { Type: ty }, { n: &Type }).parse()); + p.push_value(q!(Vars { Type: ty }, { n: Type }).parse()); p.push_punct(def_site()); p.push_value(q!(Vars {}, { _parent: &dyn Node }).parse()); @@ -381,6 +402,18 @@ fn create_method_sig(ty: &Type) -> Signature { } } + fn mk(ident: Ident, ty: &Type) -> Signature { + mk_exact( + ident, + &Type::Reference(TypeReference { + and_token: def_site(), + lifetime: None, + mutability: None, + elem: Box::new(ty.clone()), + }), + ) + } + match ty { Type::Array(_) => unimplemented!("type: array type"), Type::BareFn(_) => unimplemented!("type: fn type"), @@ -422,7 +455,17 @@ fn create_method_sig(ty: &Type) -> Signature { let ident = method_name(arg) .new_ident_with(|v| v.replace("visit_", "visit_opt_")); - return mk(ident, ty); + if let Some(item) = extract_vec(arg) { + return mk_exact( + ident, + &q!(Vars { item}, { Option<&[item]> }).parse(), + ); + } + + return mk_exact( + ident, + &q!(Vars { arg }, { Option<&arg> }).parse(), + ); } _ => unimplemented!("generic parameter other than type"), } @@ -441,6 +484,7 @@ fn create_method_sig(ty: &Type) -> Signature { let orig_name = method_name(arg); let mut ident = orig_name.new_ident_with(|v| v.to_plural()); + // Rename if name conflicts if orig_name == ident.to_string() { ident = ident.new_ident_with(|v| format!("{}_vec", v)); } @@ -535,11 +579,22 @@ fn create_method_body(ty: &Type) -> Block { GenericArgument::Type(arg) => { let ident = method_name(arg); - return q!( - Vars { ident }, - ({ n.iter().for_each(|v| { self.ident(v, _parent) }) }) - ) - .parse(); + return if is_option(arg) { + q!( + Vars { ident }, + ({ + n.iter() + .for_each(|v| self.ident(v.as_ref(), _parent)) + }) + ) + .parse() + } else { + q!( + Vars { ident }, + ({ n.iter().for_each(|v| { self.ident(v, _parent) }) }) + ) + .parse() + }; } _ => unimplemented!("generic parameter other than type"), } @@ -589,6 +644,76 @@ fn add_required(types: &mut Vec, ty: &Type) { } } +fn is_option(ty: &Type) -> bool { + match ty { + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + + if !last.arguments.is_empty() { + if last.ident == "Option" { + return true; + } + } + } + _ => {} + } + + false +} + +fn extract_vec(ty: &Type) -> Option<&Type> { + match ty { + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + + if last.ident == "Vec" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => return Some(arg), + _ => {} + } + } + _ => {} + } + } + } + _ => {} + } + + None +} + +fn is_opt_vec(ty: &Type) -> bool { + match ty { + Type::Path(p) => { + let last = p.path.segments.last().unwrap(); + + if !last.arguments.is_empty() { + if last.ident == "Option" { + match &last.arguments { + PathArguments::AngleBracketed(tps) => { + let arg = tps.args.first().unwrap(); + + match arg { + GenericArgument::Type(arg) => return extract_vec(arg).is_some(), + _ => {} + } + } + _ => {} + } + } + } + } + + _ => {} + } + + false +} + fn skip(ty: &Type) -> bool { match ty { Type::Path(p) => { From 771ae0be71f9f60673d6f75412bd66b7a9e39e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 23:00:56 +0900 Subject: [PATCH 28/32] Done --- ecmascript/visit/macros/src/lib.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index aa1492cad9b3..a3027e16a57b 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -3,10 +3,10 @@ use pmutil::{q, IdentExt}; use proc_macro2::Ident; use swc_macros_common::{call_site, def_site}; use syn::{ - parse_quote::parse, punctuated::Punctuated, spanned::Spanned, Arm, Block, Expr, ExprBlock, - ExprMatch, FieldValue, Fields, GenericArgument, Index, Item, ItemTrait, Member, Path, - PathArguments, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMethod, Type, TypePath, - TypeReference, VisPublic, Visibility, + parse_quote::parse, punctuated::Punctuated, spanned::Spanned, Arm, AttrStyle, Attribute, Block, + Expr, ExprBlock, ExprMatch, FieldValue, Fields, GenericArgument, Index, Item, ItemTrait, + Member, Path, PathArguments, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMethod, + Type, TypePath, TypeReference, VisPublic, Visibility, }; /// This creates `Visit`. This is extensible visitor generator, and it @@ -132,7 +132,15 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { }); } - methods.sort_by_cached_key(|v| v.sig.ident.to_string()); + methods.iter_mut().for_each(|v| { + v.attrs.push(Attribute { + pound_token: def_site(), + style: AttrStyle::Outer, + bracket_token: def_site(), + path: q!({ allow }).parse(), + tokens: q!({ (unused_variables) }).parse(), + }); + }); tokens.push_tokens(&ItemTrait { attrs: vec![], @@ -180,7 +188,7 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { Vars { binding_ident: &binding_ident }, - { &binding_ident.as_ref().map(|v| &**v) } + { binding_ident.as_ref().map(|v| &**v) } ) .parse() } else { @@ -482,7 +490,13 @@ fn create_method_sig(ty: &Type) -> Signature { match arg { GenericArgument::Type(arg) => { let orig_name = method_name(arg); - let mut ident = orig_name.new_ident_with(|v| v.to_plural()); + let mut ident = orig_name.new_ident_with(|v| { + let v = v.to_plural(); + if is_option(arg) { + return v.replace("visit_opt_", "visit_opt_vec_"); + } + return v.to_plural(); + }); // Rename if name conflicts if orig_name == ident.to_string() { From 2bb65e160774288b95edd14340dae54e97486b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Wed, 1 Apr 2020 23:34:37 +0900 Subject: [PATCH 29/32] Removed outdated doc comments --- ecmascript/visit/macros/src/lib.rs | 67 +----------------------------- 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index a3027e16a57b..3759db5f245b 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -17,75 +17,10 @@ use syn::{ /// /// If there's a need, I'll publish the macro with generic name. /// -/// - will be extended create `VisitMut` and `Fold` in future +/// - will be extended to create `VisitMut` and `Fold` in future /// /// (If there's a request) /// -/// -/// # Basic -/// -/// - Method name is determined based on type's name. -/// - All arguments follow the syntax of argument. (This makes rustfmt happy) -/// -/// -/// # Struct -/// -/// ```ignore -/// pub struct Struct { -/// pub field: String, -/// } -/// -/// define!(Struct { field }, String); -/// ``` -/// -/// generates (code which behaves like) -/// -/// ``` -/// pub trait Visit { -/// fn visit_struct(&mut self, n: &Struct) { -/// self.visit_string(&n.field) -/// } -/// -/// fn visit_string(&mut self, n: &String) {} -/// } -/// ``` -/// -/// -/// -/// # Enum -/// -/// ```ignore -/// pub enum Enum { -/// StructLike { field: String }, -/// TupleLike(String, u64), -/// UnitLike, -/// } -/// -/// define!( -/// Value(StructLike { field }, TupleLike(a, b), UnitLike), -/// String, -/// u64 -/// ); -/// ``` -/// -/// generates (code which behaves like) -/// -/// ``` -/// pub trait Visit { -/// fn visit_enum(&mut self, n: &Enum) { -/// match n { -/// Enum::StructLike { field } => self.visit_string(field), -/// Enum::TupleLike(_0, _1) => { -/// self.visit_string(_0); -/// self.visit_u64(_1); -/// } -/// Enum::UnitLike => {} -/// } -/// } -/// fn visit_string(&mut self, n: &String) {} -/// fn visit_u64(&mut self, n: &u64) {} -/// } -/// ``` #[proc_macro] pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { let block: Block = parse(tts.into()); From 5a1687cdba56397edb67db40036277687814f012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 2 Apr 2020 01:28:39 +0900 Subject: [PATCH 30/32] fmt --- ecmascript/visit/macros/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 3759db5f245b..a791a0f94c73 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -20,7 +20,6 @@ use syn::{ /// - will be extended to create `VisitMut` and `Fold` in future /// /// (If there's a request) -/// #[proc_macro] pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { let block: Block = parse(tts.into()); From c6d105d8b84ef94e9e2183496517064ac29e9323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 2 Apr 2020 10:12:22 +0900 Subject: [PATCH 31/32] Split default --- ecmascript/visit/macros/src/lib.rs | 60 +++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index a791a0f94c73..52812932a287 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -1,10 +1,11 @@ use inflector::Inflector; use pmutil::{q, IdentExt}; use proc_macro2::Ident; +use std::mem::replace; use swc_macros_common::{call_site, def_site}; use syn::{ parse_quote::parse, punctuated::Punctuated, spanned::Spanned, Arm, AttrStyle, Attribute, Block, - Expr, ExprBlock, ExprMatch, FieldValue, Fields, GenericArgument, Index, Item, ItemTrait, + Expr, ExprBlock, ExprMatch, FieldValue, Fields, FnArg, GenericArgument, Index, Item, ItemTrait, Member, Path, PathArguments, ReturnType, Signature, Stmt, Token, TraitItem, TraitItemMethod, Type, TypePath, TypeReference, VisPublic, Visibility, }; @@ -74,6 +75,46 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { path: q!({ allow }).parse(), tokens: q!({ (unused_variables) }).parse(), }); + + let fn_name = v.sig.ident.clone(); + let default_body = replace( + &mut v.default, + Some( + q!(Vars { fn_name: &fn_name }, { + { + fn_name(self, n, _parent) + } + }) + .parse(), + ), + ) + .clone(); + + let arg_ty = v + .sig + .inputs + .iter() + .skip(1) + .next() + .map(|v| match *v { + FnArg::Typed(ref pat) => &pat.ty, + _ => unreachable!(), + }) + .unwrap(); + + tokens.push_tokens(&q!( + Vars { + fn_name, + default_body, + Type: arg_ty, + }, + { + #[allow(unused_variables)] + fn fn_name(_visitor: &mut V, n: Type, _parent: &dyn Node) { + default_body + } + } + )) }); tokens.push_tokens(&ItemTrait { @@ -84,7 +125,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { unsafety: None, auto_token: None, trait_token: def_site(), - ident: Ident::new("Visit", def_site()), + ident: Ident::new("Visit", call_site()), generics: Default::default(), colon_token: None, supertraits: Default::default(), @@ -137,7 +178,7 @@ fn make_arm_from_struct(path: &Path, variant: &Fields) -> Arm { } let stmt = q!(Vars { expr, visit_name }, { - self.visit_name(expr, n as _); + _visitor.visit_name(expr, n as _); }) .parse(); stmts.push(stmt); @@ -197,7 +238,7 @@ fn method_sig(ty: &Type) -> Signature { paren_token: def_site(), inputs: { let mut p = Punctuated::default(); - p.push_value(q!(Vars {}, { &self }).parse()); + p.push_value(q!(Vars {}, { &mut self }).parse()); p.push_punct(def_site()); p.push_value(q!(Vars { Type: ty }, { n: &Type }).parse()); p.push_punct(def_site()); @@ -331,7 +372,7 @@ fn create_method_sig(ty: &Type) -> Signature { paren_token: def_site(), inputs: { let mut p = Punctuated::default(); - p.push_value(q!(Vars {}, { &self }).parse()); + p.push_value(q!(Vars {}, { &mut self }).parse()); p.push_punct(def_site()); p.push_value(q!(Vars { Type: ty }, { n: Type }).parse()); p.push_punct(def_site()); @@ -504,7 +545,7 @@ fn create_method_body(ty: &Type) -> Block { Vars { ident }, ({ match n { - Some(n) => self.ident(n, _parent), + Some(n) => _visitor.ident(n, _parent), None => {} } }) @@ -531,15 +572,16 @@ fn create_method_body(ty: &Type) -> Block { q!( Vars { ident }, ({ - n.iter() - .for_each(|v| self.ident(v.as_ref(), _parent)) + n.iter().for_each(|v| { + _visitor.ident(v.as_ref(), _parent) + }) }) ) .parse() } else { q!( Vars { ident }, - ({ n.iter().for_each(|v| { self.ident(v, _parent) }) }) + ({ n.iter().for_each(|v| _visitor.ident(v, _parent)) }) ) .parse() }; From 723e8fab8474a9a6a5cb65f2af9e16d28ff21835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 2 Apr 2020 18:16:11 +0900 Subject: [PATCH 32/32] Update ecmascript/visit/macros/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartek Iwańczuk --- ecmascript/visit/macros/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecmascript/visit/macros/src/lib.rs b/ecmascript/visit/macros/src/lib.rs index 52812932a287..5f5a4e1d9154 100644 --- a/ecmascript/visit/macros/src/lib.rs +++ b/ecmascript/visit/macros/src/lib.rs @@ -110,7 +110,7 @@ pub fn define(tts: proc_macro::TokenStream) -> proc_macro::TokenStream { }, { #[allow(unused_variables)] - fn fn_name(_visitor: &mut V, n: Type, _parent: &dyn Node) { + pub fn fn_name(_visitor: &mut V, n: Type, _parent: &dyn Node) { default_body } }