Rust宏编程库cairo-lang-macro的使用,Cairo语言宏扩展与代码生成工具

Cairo Lang Macro

这个crate为Cairo语言提供了编写Scarb procedural宏的API。

安装

在项目目录中运行以下Cargo命令:

cargo add cairo-lang-macro

或者在Cargo.toml中添加以下行:

cairo-lang-macro = "0.2.0"

示例使用

以下是一个使用cairo-lang-macro创建自定义derive宏的完整示例:

use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Parse the input tokens into a syntax tree
    let input = parse_macro_input!(input as DeriveInput);
    
    // Get the name of the struct/enum we're deriving for
    let name = input.ident;
    
    // Build the output, possibly using quote! macro
    let output = quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("Hello, Macro! My name is {}!", stringify!(#name));
            }
        }
    };
    
    // Return the generated code as TokenStream
    TokenStream::from(output)
}

更复杂的示例

这是一个更复杂的示例,展示了如何使用cairo-lang-macro创建属性宏:

use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

#[proc_mature_attribute]
pub fn log_execution_time(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // Parse the input function
    let input_fn = parse_macro_input!(item as ItemFn);
    
    // Get function details
    let fn_name = &input_fn.sig.ident;
    let fn_block = &input_fn.block;
    
    // Generate the output with timing logic
    let output = quote! {
        fn #fn_name() {
            use std::time::Instant;
            let start = Instant::now();
            
            #fn_block
            
            let duration = start.elapsed();
            println!("Function {} took {:?}", stringify!(#fn_name), duration);
        }
    };
    
    TokenStream::from(output)
}

完整示例

下面是一个完整的项目示例,展示如何使用cairo-lang-macro:

  1. 首先创建一个新的库项目:
cargo new --lib cairo_macro_example
cd cairo_macro_example
  1. 添加依赖到Cargo.toml:
[lib]
proc-macro = true

[dependencies]
cairo-lang-macro = "0.2.0"
syn = { version = "2.0", features = ["full"] }
quote = "1.0"
  1. 在src/lib.rs中实现自定义宏:
use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

// 自定义derive宏实现
#[proc_macro_derive(VersionInfo)]
pub fn version_info_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    
    let output = quote! {
        impl VersionInfo for #name {
            fn version() -> &'static str {
                env!("CARGO_PKG_VERSION")
            }
            
            fn author() -> &'static str {
                env!("CARGO_PKG_AUTHORS")
            }
        }
    };
    
    TokenStream::from(output)
}

// 属性宏实现
#[proc_macro_attribute]
pub fn debug_log(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input_fn = parse_macro_input!(item as ItemFn);
    let fn_name = &input_fn.sig.ident;
    let fn_block = &input_fn.block;
    
    let output = quote! {
        fn #fn_name() {
            println!("[DEBUG] Entering function: {}", stringify!(#fn_name));
            #fn_block
            println!("[DEBUG] Exiting function: {}", stringify!(#fn_name));
        }
    };
    
    TokenStream::from(output)
}
  1. 在另一个项目中使用这些宏:
use cairo_macro_example::{VersionInfo, debug_log};

#[derive(VersionInfo)]
struct MyStruct;

#[debug_log]
fn my_function() {
    println!("Doing some work...");
}

fn main() {
    println!("MyStruct version: {}", MyStruct::version());
    println!("MyStruct author: {}", MyStruct::author());
    my_function();
}

使用场景

cairo-lang-macro特别适用于:

  • 为Cairo语言创建自定义derive宏
  • 开发代码生成工具
  • 实现领域特定语言(DSL)
  • 创建编译时验证和转换

版本信息

当前版本:v0.2.0
最小支持Rust版本:v1.73.0
许可证:MIT


1 回复

以下是关于cairo-lang-macro的完整示例demo,基于您提供的内容:

1. 简单宏完整示例

use cairo_lang_macro::proc_macro;
use proc_macro::TokenStream;

/// 一个简单的宏,将输入原样返回
#[proc_macro]
pub fn identity_macro(input: TokenStream) -> TokenStream {
    // 直接返回输入不做任何处理
    input
}

// 使用示例:
// let result = identity_macro!(println!("Hello"));

2. 属性宏完整示例

use cairo_lang_macro::proc_macro_attribute;
use proc_macro::TokenStream;

/// 属性宏示例,添加函数调用日志
#[proc_macro_attribute]
pub fn log_function(attr: TokenStream, item: TokenStream) -> TokenStream {
    // 解析输入函数
    let mut input_fn: syn::ItemFn = syn::parse(item).unwrap();
    
    // 获取函数名
    let fn_name = &input_fn.sig.ident;
    
    // 在函数体开头插入日志语句
    let new_stmt: syn::Stmt = syn::parse_quote! {
        println!("调用函数: {}", stringify!(#fn_name));
    };
    
    input_fn.block.stmts.insert(0, new_stmt);
    
    // 返回修改后的TokenStream
    TokenStream::from(quote::quote! { #input_fn })
}

// 使用示例:
// #[log_function]
// fn my_function() {
//     println!("执行中...");
// }

3. 派生宏完整示例

use cairo_lang_macro::{proc_macro_derive, parse_macro_input, DeriveInput};
use proc_macro::TokenStream;
use quote::quote;

/// 派生宏示例,为结构体生成默认实现
#[proc_macro_derive(DefaultStruct)]
pub fn default_struct_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    
    // 生成默认实现
    let expanded = quote! {
        impl #name {
            pub fn default() -> Self {
                Self {
                    // 默认字段值
                }
            }
        }
    };
    
    expanded.into()
}

// 使用示例:
// #[derive(DefaultStruct)]
// struct MyStruct {
//     field1: u32,
//     field2: String,
// }

4. 代码生成完整示例

use cairo_lang_macro::proc_macro;
use proc_macro::{TokenStream, Ident, Span};
use quote::quote;

/// 生成带有getter方法的简单结构体
#[proc_macro]
pub fn generate_getter_struct(input: TokenStream) -> TokenStream {
    let struct_name = Ident::new("Person", Span::call_site());
    
    let output = quote! {
        struct #struct_name {
            name: String,
            age: u32,
        }
        
        impl #struct_name {
            pub fn get_name(&self) -> &str {
                &self.name
            }
            
            pub fn get_age(&self) -> u32 {
                self.age
            }
        }
    };
    
    output.into()
}

// 使用示例:
// generate_getter_struct!();

5. 语法树操作完整示例

use cairo_lang_macro::{parse_macro_input, DeriveInput};
use proc_macro::TokenStream;
use quote::quote;

/// 为结构体生成builder模式实现
#[proc_macro_derive(Builder)]
pub fn builder_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    let builder_name = Ident::new(&format!("{}Builder", name), Span::call_site());
    
    let expanded = quote! {
        struct #builder_name {
            inner: #name,
        }
        
        impl #builder_name {
            fn new() -> Self {
                Self {
                    inner: #name::default(),
                }
            }
            
            fn build(self) -> #name {
                self.inner
            }
        }
    };
    
    expanded.into()
}

// 使用示例:
// #[derive(Builder, Default)]
// struct User {
//     id: u64,
//     name: String,
// }
回到顶部