Skip to content

Commit

Permalink
Parse attr arguments
Browse files Browse the repository at this point in the history
commit-id:b3fd46d7
  • Loading branch information
maciektr committed Apr 14, 2024
1 parent 055a985 commit ecf4ec3
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 43 deletions.
22 changes: 17 additions & 5 deletions plugins/cairo-lang-macro-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ use syn::{parse_macro_input, ItemFn};
/// Note, that this macro can be used multiple times, to define multiple independent attribute macros.
#[proc_macro_attribute]
pub fn attribute_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
macro_helper(input, quote!(::cairo_lang_macro::ExpansionKind::Attr))
macro_helper(
input,
quote!(::cairo_lang_macro::ExpansionKind::Attr),
quote!(::cairo_lang_macro::ExpansionFunc::Attr),
)
}

/// Constructs the inline macro implementation.
Expand All @@ -21,7 +25,11 @@ pub fn attribute_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
/// Note, that this macro can be used multiple times, to define multiple independent attribute macros.
#[proc_macro_attribute]
pub fn inline_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
macro_helper(input, quote!(::cairo_lang_macro::ExpansionKind::Inline))
macro_helper(
input,
quote!(::cairo_lang_macro::ExpansionKind::Inline),
quote!(::cairo_lang_macro::ExpansionFunc::Other),
)
}

/// Constructs the derive macro implementation.
Expand All @@ -31,10 +39,14 @@ pub fn inline_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
/// Note, that this macro can be used multiple times, to define multiple independent attribute macros.
#[proc_macro_attribute]
pub fn derive_macro(_args: TokenStream, input: TokenStream) -> TokenStream {
macro_helper(input, quote!(::cairo_lang_macro::ExpansionKind::Derive))
macro_helper(
input,
quote!(::cairo_lang_macro::ExpansionKind::Derive),
quote!(::cairo_lang_macro::ExpansionFunc::Other),
)
}

fn macro_helper(input: TokenStream, kind: impl ToTokens) -> TokenStream {
fn macro_helper(input: TokenStream, kind: impl ToTokens, func: impl ToTokens) -> TokenStream {
let item: ItemFn = parse_macro_input!(input as ItemFn);
let original_item_name = item.sig.ident.to_string();
let item = hide_name(item);
Expand All @@ -56,7 +68,7 @@ fn macro_helper(input: TokenStream, kind: impl ToTokens) -> TokenStream {
::cairo_lang_macro::ExpansionDefinition{
name: #original_item_name,
kind: #kind,
fun: #item_name,
fun: #func(#item_name),
};
};
TokenStream::from(expanded)
Expand Down
1 change: 1 addition & 0 deletions plugins/cairo-lang-macro-stable/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub struct StableProcMacroResult {
#[repr(C)]
pub struct StableResultWrapper {
pub input: StableTokenStream,
pub input_attr: StableTokenStream,
pub output: StableProcMacroResult,
}

Expand Down
18 changes: 15 additions & 3 deletions plugins/cairo-lang-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ pub struct ExpansionDefinition {
pub fun: ExpansionFunc,
}

type ExpansionFunc = fn(TokenStream) -> ProcMacroResult;
#[derive(Clone)]
pub enum ExpansionFunc {
Attr(fn(TokenStream, TokenStream) -> ProcMacroResult),
Other(fn(TokenStream) -> ProcMacroResult),
}

// type ExpansionFunc = fn(TokenStream) -> ProcMacroResult;

/// Distributed slice for storing procedural macro code expansion capabilities.
///
Expand Down Expand Up @@ -89,24 +95,30 @@ pub unsafe extern "C" fn free_expansions_list(list: StableExpansionsList) {
#[no_mangle]
pub unsafe extern "C" fn expand(
item_name: *const c_char,
stable_attr: cairo_lang_macro_stable::StableTokenStream,
stable_token_stream: cairo_lang_macro_stable::StableTokenStream,
) -> cairo_lang_macro_stable::StableResultWrapper {
let token_stream = TokenStream::from_stable(&stable_token_stream);
let attr_token_stream = TokenStream::from_stable(&stable_attr);
let item_name = CStr::from_ptr(item_name).to_string_lossy().to_string();
let fun = MACRO_DEFINITIONS_SLICE
.iter()
.find_map(|m| {
if m.name == item_name.as_str() {
Some(m.fun)
Some(m.fun.clone())
} else {
None
}
})
.expect("procedural macro not found");
let result = fun(token_stream);
let result = match fun {
ExpansionFunc::Attr(fun) => fun(attr_token_stream, token_stream),
ExpansionFunc::Other(fun) => fun(token_stream),
};
let result: StableProcMacroResult = result.into_stable();
cairo_lang_macro_stable::StableResultWrapper {
input: stable_token_stream,
input_attr: stable_attr,
output: result,
}
}
Expand Down
9 changes: 7 additions & 2 deletions scarb/src/compiler/plugin/proc_macro/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,25 @@ impl ProcMacroInstance {
pub(crate) fn generate_code(
&self,
item_name: SmolStr,
attr: TokenStream,
token_stream: TokenStream,
) -> ProcMacroResult {
// This must be manually freed with call to from_owned_stable.
let stable_token_stream = token_stream.into_stable();
let stable_attr = attr.into_stable();
// Allocate proc macro name.
let item_name = CString::new(item_name.to_string()).unwrap().into_raw();
// Call FFI interface for code expansion.
// Note that `stable_result` has been allocated by the dynamic library.
let stable_result = (self.plugin.vtable.expand)(item_name, stable_token_stream);
let stable_result =
(self.plugin.vtable.expand)(item_name, stable_attr, stable_token_stream);
// Free proc macro name.
let _ = unsafe { CString::from_raw(item_name) };
// Free the memory allocated by the `stable_token_stream`.
// This will call `CString::from_raw` under the hood, to take ownership.
unsafe {
TokenStream::from_owned_stable(stable_result.input);
TokenStream::from_owned_stable(stable_result.input_attr);
};
// Create Rust representation of the result.
// Note, that the memory still needs to be freed on the allocator side!
Expand Down Expand Up @@ -201,7 +205,8 @@ impl Expansion {

type ListExpansions = extern "C" fn() -> StableExpansionsList;
type FreeExpansionsList = extern "C" fn(StableExpansionsList);
type ExpandCode = extern "C" fn(*const c_char, StableTokenStream) -> StableResultWrapper;
type ExpandCode =
extern "C" fn(*const c_char, StableTokenStream, StableTokenStream) -> StableResultWrapper;
type FreeResult = extern "C" fn(StableProcMacroResult);
type PostProcessCallback = extern "C" fn(StablePostProcessContext) -> StablePostProcessContext;

Expand Down
40 changes: 25 additions & 15 deletions scarb/src/compiler/plugin/proc_macro/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl ProcMacroHostPlugin {
&self,
db: &dyn SyntaxGroup,
item_ast: ast::ModuleItem,
) -> (Option<ProcMacroId>, TokenStream) {
) -> (Option<(ProcMacroId, TokenStream)>, TokenStream) {
let mut item_builder = PatchBuilder::new(db);
let input = match item_ast {
ast::ModuleItem::Struct(struct_ast) => {
Expand Down Expand Up @@ -223,7 +223,7 @@ impl ProcMacroHostPlugin {
db: &dyn SyntaxGroup,
builder: &mut PatchBuilder<'_>,
attrs: Vec<ast::Attribute>,
) -> Option<ProcMacroId> {
) -> Option<(ProcMacroId, TokenStream)> {
let mut expansion = None;
for attr in attrs {
if expansion.is_none() {
Expand All @@ -232,8 +232,11 @@ impl ProcMacroHostPlugin {
structured_attr.id.clone(),
ExpansionKind::Attr,
));
if found.is_some() {
expansion = found;
if let Some(found) = found {
let mut args_builder = PatchBuilder::new(db);
args_builder.add_node(attr.arguments(db).as_syntax_node());
let args = TokenStream::new(args_builder.code);
expansion = Some((found, args));
// Do not add the attribute for found expansion.
continue;
}
Expand Down Expand Up @@ -300,9 +303,11 @@ impl ProcMacroHostPlugin {

let mut derived_code = PatchBuilder::new(db);
for derive in derives {
let result = self
.instance(derive.package_id)
.generate_code(derive.expansion.name.clone(), token_stream.clone());
let result = self.instance(derive.package_id).generate_code(
derive.expansion.name.clone(),
TokenStream::empty(),
token_stream.clone(),
);

// Register diagnostics.
all_diagnostics.extend(result.diagnostics);
Expand Down Expand Up @@ -353,12 +358,15 @@ impl ProcMacroHostPlugin {
fn expand_attribute(
&self,
input: ProcMacroId,
args: TokenStream,
token_stream: TokenStream,
stable_ptr: SyntaxStablePtrId,
) -> PluginResult {
let result = self
.instance(input.package_id)
.generate_code(input.expansion.name.clone(), token_stream.clone());
let result = self.instance(input.package_id).generate_code(
input.expansion.name.clone(),
args.clone(),
token_stream.clone(),
);

// Handle token stream.
if result.token_stream.is_empty() {
Expand Down Expand Up @@ -574,10 +582,10 @@ impl MacroPlugin for ProcMacroHostPlugin {
// Expand first attribute.
// Note that we only expand the first attribute, as we assume that the rest of the attributes
// will be handled by a subsequent call to this function.
if let (Some(input), token_stream) = self.parse_attribute(db, item_ast.clone()) {
if let (Some((input, args)), token_stream) = self.parse_attribute(db, item_ast.clone()) {
let token_stream = token_stream.with_metadata(stream_metadata.clone());
let stable_ptr = item_ast.clone().stable_ptr().untyped();
return self.expand_attribute(input, token_stream, stable_ptr);
return self.expand_attribute(input, args, token_stream, stable_ptr);
}

// Expand all derives.
Expand Down Expand Up @@ -640,9 +648,11 @@ impl InlineMacroExprPlugin for ProcMacroInlinePlugin {
let stable_ptr = syntax.clone().stable_ptr().untyped();

let token_stream = TokenStream::from_syntax_node(db, syntax.as_syntax_node());
let result = self
.instance()
.generate_code(self.expansion.name.clone(), token_stream);
let result = self.instance().generate_code(
self.expansion.name.clone(),
TokenStream::empty(),
token_stream,
);
// Handle diagnostics.
let diagnostics = into_cairo_diagnostics(result.diagnostics, stable_ptr);
let token_stream = result.token_stream.clone();
Expand Down
Loading

0 comments on commit ecf4ec3

Please sign in to comment.