Skip to content

Commit

Permalink
refactor: use syn, quote and proc-macro2.
Browse files Browse the repository at this point in the history
  • Loading branch information
rzvxa committed Jul 21, 2024
1 parent b4c531d commit faf24ec
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 47 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions crates/oxc_ast/src/ast/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
///
/// ```
/// inherit_variants! {
/// #[repr(C, u8)]
/// #[ast]
/// enum Statement<'a> {
/// pub enum Statement<'a> {
/// BlockStatement(Box<'a, BlockStatement<'a>>) = 0,
Expand All @@ -35,7 +35,7 @@
/// expands to:
///
/// ```
/// #[repr(C, u8)]
/// #[ast]
/// enum Statement<'a> {
/// pub enum Statement<'a> {
/// BlockStatement(Box<'a, BlockStatement<'a>>) = 0,
Expand Down Expand Up @@ -733,7 +733,7 @@ pub(crate) use inherit_variants;
/// Equality of discriminants is checked with a compile-time assertion.
///
/// # SAFETY
/// Both enums must be `#[repr(C, u8)]` or using this macro is unsound.
/// Both enums must be `#[ast]` or using this macro is unsound.
///
/// # Expansion
///
Expand Down Expand Up @@ -936,7 +936,7 @@ pub(crate) use shared_enum_variants;

/// Macro to get discriminant of an enum.
/// # SAFETY
/// Enum must be `#[repr(C, u8)]` or using this macro is unsound.
/// Enum must be `#[ast]` or using this macro is unsound.
/// <https://doc.rust-lang.org/std/mem/fn.discriminant.html>
macro_rules! discriminant {
($ty:ident :: $variant:ident) => {{
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_ast_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ workspace = true
[lib]
proc-macro = true
doctest = false

[dependencies]
quote = { workspace = true }
syn = { workspace = true, features = ["full"] }
proc-macro2 = { workspace = true }
65 changes: 22 additions & 43 deletions crates/oxc_ast_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use proc_macro::{TokenStream, TokenTree};
use std::str::FromStr;

enum ItemKind {
Enum,
Struct,
Unknown,
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};

fn enum_repr(enum_: &syn::ItemEnum) -> TokenStream2 {
if enum_.variants.iter().any(|var| !matches!(var.fields, syn::Fields::Unit)) {
quote!(#[repr(C, u8)])
} else {
quote!(#[repr(C)])
}
}

/// Attach to AST node type (struct or enum), to signal to codegen to create visitor for this type.
Expand All @@ -22,47 +25,23 @@ enum ItemKind {
#[proc_macro_attribute]
#[allow(clippy::missing_panics_doc)]
pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
let mut input = input.into_iter();
let mut stream = TokenStream::new();
let mut output = TokenStream::from_str("#[derive(::oxc_ast_macros::Ast)]").unwrap();
let input = syn::parse_macro_input!(input as syn::Item);

let mut item_kind = ItemKind::Unknown;
let repr = match &input {
syn::Item::Enum(enum_) => enum_repr(enum_),
syn::Item::Struct(_) => quote!(#[repr(C)]),

while let Some(next) = input.next() {
if let TokenTree::Ident(ident) = &next {
match ident.to_string().as_str() {
"enum" => {
assert!(matches!(item_kind, ItemKind::Unknown));
item_kind = ItemKind::Enum;
stream.extend(Some(next));
break;
}
"struct" => {
assert!(matches!(item_kind, ItemKind::Unknown));
item_kind = ItemKind::Struct;
stream.extend(Some(next));
break;
}
_ => {}
}
_ => {
unreachable!()
}

stream.extend(Some(next));
}

// append the remained of the input tokens to the stream
stream.extend(input);

let repr = match item_kind {
ItemKind::Enum => TokenStream::from_str("#[repr(C, u8)]").unwrap(),
// ItemKind::Struct => TokenStream::from_str("#[repr(C)]").unwrap(),
ItemKind::Struct => TokenStream::default(),
ItemKind::Unknown => unreachable!(),
};

output.extend(repr);
output.extend(stream);
output
let expanded = quote! {
#[derive(::oxc_ast_macros::Ast)]
#repr
#input
};
TokenStream::from(expanded.into_token_stream())
}

/// Dummy derive macro for a non-existent trait `Ast`.
Expand Down

0 comments on commit faf24ec

Please sign in to comment.