Rust编译器插件库erg_compiler的使用,erg_compiler为Rust语言提供强大的编译时扩展和元编程支持

Rust编译器插件库erg_compiler的使用

erg_compiler为Rust语言提供强大的编译时扩展和元编程支持。以下是关于如何使用它的详细信息:

作为Python库使用

erg_compiler可以通过pyo3/maturin构建为Python库。

示例代码

import erg_compiler

# 执行模块并获取变量
module = erg_compiler.exec_module(".i = 1")
# 假设有一个foo.er文件:
# .bar = 1
foo = erg_compiler.__import__("foo")
assert module.i == 1
assert foo.bar == 1
import erg_compiler
erg_parser = erg_compiler.erg_parser
erg_ast = erg_compiler.erg_parser.ast

# 解析并修改AST
module = erg_parser.parse(".i = 1")
d = module.pop()
d.sig = erg_ast.VarSignature.new(erg_ast.Identifier.public("j"), None)
module.push(d)
ast = erg_ast.AST.new("test", module)
code = erg_compiler.compile_ast(ast)
exec(code)
assert j == 1

完整示例

# erg_compiler_demo.py
import erg_compiler

def main():
    # 示例1: 执行简单模块
    module = erg_compiler.exec_module(".greeting = 'Hello, World!'")
    print(module.greeting)  # 输出: Hello, World!

    # 示例2: 解析和修改AST
    erg_parser = erg_compiler.erg_parser
    erg_ast = erg_compiler.erg_parser.ast
    
    module = erg_parser.parse(".x = 42")
    decl = module.pop()
    decl.sig = erg_ast.VarSignature.new(erg_ast.Identifier.public("answer"), None)
    module.push(decl)
    
    ast = erg_ast.AST.new("demo", module)
    code = erg_compiler.compile_ast(ast)
    exec(code)
    print(answer)  # 输出: 42

if __name__ == "__main__":
    main()

安装方法

调试安装(使用venv)

python -m venv .venv
source .venv/bin/activate
maturin develop --features pylib_compiler

发布安装

maturin build -i python --release --features pylib_compiler
pip install <输出wheel文件>

作为Rust库使用

安装

cargo add erg_compiler

或在Cargo.toml中添加:

erg_compiler = "0.6.52"

项目信息

  • 版本: 0.6.52
  • 许可证: MIT OR Apache-2.0
  • 大小: 499 KiB

erg_compiler提供了强大的编译时扩展能力,通过Python接口可以方便地进行元编程和AST操作。

完整示例demo

以下是基于erg_compiler的完整使用示例,展示了如何执行模块、解析和修改AST:

# erg_compiler_complete_demo.py
import erg_compiler
from erg_compiler.erg_parser import ast

def execute_simple_module():
    """执行简单模块示例"""
    print("=== 执行简单模块 ===")
    # 执行包含变量的简单模块
    module = erg_compiler.exec_module(".message = 'Hello from Erg'")
    print(f"模块变量值: {module.message}")  # 输出: Hello from Erg

def parse_and_modify_ast():
    """解析和修改AST示例"""
    print("\n=== 解析和修改AST ===")
    # 解析原始代码
    original_code = ".value = 100"
    parsed = erg_compiler.erg_parser.parse(original_code)
    
    # 修改AST节点
    decl = parsed.pop()
    # 将变量名从value改为count
    decl.sig = ast.VarSignature.new(ast.Identifier.public("count"), None)
    parsed.push(decl)
    
    # 编译修改后的AST
    modified_ast = ast.AST.new("modified", parsed)
    compiled_code = erg_compiler.compile_ast(modified_ast)
    
    # 执行编译后的代码
    exec(compiled_code)
    print(f"修改后的变量值: {count}")  # 输出: 100

def import_external_module():
    """导入外部模块示例"""
    print("\n=== 导入外部模块 ===")
    # 假设有外部模块math.er包含: .pi = 3.1415926
    try:
        math_mod = erg_compiler.__import__("math")
        print(f"导入的PI值: {math_mod.pi}")  # 输出: 3.1415926
    except Exception as e:
        print(f"导入模块失败: {e}")

if __name__ == "__main__":
    execute_simple_module()
    parse_and_modify_ast()
    import_external_module()

这个完整示例展示了erg_compiler的三个主要功能:

  1. 直接执行Erg模块代码
  2. 解析和修改抽象语法树(AST)
  3. 导入外部Erg模块

运行此示例前,请确保已按照前面介绍的安装方法正确安装erg_compiler。


1 回复

Rust编译器插件库erg_compiler使用指南

简介

erg_compiler是一个为Rust语言设计的编译器插件库,它提供了强大的编译时扩展和元编程支持。这个库允许开发者在编译阶段执行自定义逻辑,扩展Rust语言的语法和功能。

主要特性

  • 编译时代码生成
  • 自定义语法扩展
  • 元编程支持
  • 类型系统增强
  • 编译时验证

安装方法

在Cargo.toml中添加依赖:

[dependencies]
erg_compiler = "0.1"  # 请使用最新版本

基本使用方法

1. 定义编译器插件

use erg_compiler::plugin::{CompilerPlugin, PluginResult};
use syn::{ItemFn, parse_macro_input};

#[erg_compiler::compiler_plugin]
fn my_plugin(input: TokenStream) -> TokenStream {
    // 解析输入
    let input_fn = parse_macro_input!(input as ItemFn);
    
    // 在这里处理AST并生成新的代码
    let output = quote! {
        #input_fn
        
        // 添加额外的生成代码
        fn generated_function() {
            println!("This was generated at compile time!");
        }
    };
    
    output.into()
}

2. 使用自定义属性

#[my_plugin]
fn original_function() {
    println!("Original function");
}

// 编译后会生成额外的generated_function

3. 编译时验证示例

use erg_compiler::validator::{CompileTimeValidator, ValidationError};

struct MyValidator;

impl CompileTimeValidator for MyValidator {
    fn validate(&self, item: &syn::Item) -> Result<(), ValidationError> {
        if let syn::Item::Fn(fn_item) = item {
            if fn_item.sig.ident == "unsafe_function" && !fn_item.sig.unsafety.is_some() {
                return Err(ValidationError::new(
                    "Function named 'unsafe_function' must be marked as unsafe"
                ));
            }
        }
        Ok(())
    }
}

#[erg_compiler::register_validator]
static VALIDATOR: MyValidator = MyValidator;

高级用法

1. 语法扩展

use erg_compiler::syntax_extension::{SyntaxExtension, ExtensionResult};

struct DbQueryExtension;

impl SyntaxExtension for DbQueryExtension {
    fn extend(&self, input: TokenStream) -> ExtensionResult {
        // 解析自定义语法并转换为标准Rust代码
        // ...
    }
}

#[erg_compiler::register_extension]
static DB_QUERY_EXT: DbQueryExtension = DbQueryExtension;

使用示例:

db_query! {
    SELECT * FROM users WHERE age > 18
}

2. 编译时代码生成

use erg_compiler::codegen::{CodeGenerator, CodegenContext};

struct ApiClientGenerator;

impl CodeGenerator for ApiClientGenerator {
    fn generate(&self, ctx: &CodegenContext) -> TokenStream {
        // 根据上下文生成API客户端代码
        // ...
    }
}

#[erg_compiler::register_codegen]
static API_CLIENT_GEN: ApiClientGenerator = ApiClientGenerator;

实际应用示例

1. 自动实现trait

#[erg_compiler::auto_derive]
trait JsonSerializable {
    fn to_json(&self) -> String;
}

#[derive(JsonSerializable)
struct User {
    name: String,
    age: u32,
}

// 编译器会自动生成to_json方法的实现

2. 编译时路由注册

#[erg_compiler::web_route(GET, "/users")]
fn get_users() -> Json<Vec<User>> {
    // ...
}

完整示例代码

下面是一个完整的示例,展示了如何使用erg_compiler创建自定义属性宏:

use erg_compiler::plugin::{CompilerPlugin, PluginResult};
use proc_macro::TokenStream;
use syn::{parse_macro_input, ItemFn};
use quote::quote;

// 1. 定义编译器插件
#[erg_compiler::compiler_plugin]
fn benchmark_plugin(input: TokenStream) -> TokenStream {
    // 解析输入函数
    let input_fn = parse_macro_input!(input as ItemFn);
    let fn_name = &input_fn.sig.ident;
    
    // 生成带基准测试的代码
    let output = quote! {
        #input_fn
        
        #[test]
        fn benchmark_#fn_name() {
            use std::time::Instant;
            let start = Instant::now();
            #fn_name();
            let duration = start.elapsed();
            println!("Function {} took {:?}", stringify!(#fn_name), duration);
        }
    };
    
    output.into()
}

// 2. 使用自定义属性
#[benchmark_plugin]
fn expensive_operation() {
    // 模拟耗时操作
    for _ in 0..1_000_000 {
        let _ = 1 + 1;
    }
}

// 3. 编译时验证
struct BenchmarkValidator;

impl erg_compiler::validator::CompileTimeValidator for BenchmarkValidator {
    fn validate(&self, item: &syn::Item) -> Result<(), erg_compiler::validator::ValidationError> {
        if let syn::Item::Fn(fn_item) = item {
            if fn_item.attrs.iter().any(|attr| attr.path.is_ident("benchmark_plugin")) {
                if fn_item.sig.asyncness.is_some() {
                    return Err(erg_compiler::validator::ValidationError::new(
                        "Benchmarked functions cannot be async"
                    ));
                }
            }
        }
        Ok(())
    }
}

#[erg_compiler::register_validator]
static BENCH_VALIDATOR: BenchmarkValidator = BenchmarkValidator;

注意事项

  1. 编译器插件可能会增加编译时间
  2. 复杂的元编程可能使代码难以调试
  3. 确保插件生成的代码符合Rust的安全规则
  4. 在稳定版Rust中某些功能可能受限

erg_compiler为Rust开发者提供了强大的元编程能力,可以用于创建领域特定语言(DSL)、减少样板代码、实现编译时验证等高级功能。

回到顶部