Rust插件库erg的使用,为Rust开发者提供高效代码分析和宏扩展功能

Rust插件库erg的使用,为Rust开发者提供高效代码分析和宏扩展功能

Erg编程语言

Erg Logo

Erg是一个为以下人群设计的编程语言:

  • 需要类似Rust的健壮性和良好的编译器支持,但不需要像Rust那样冗长的类型规范和内存管理模型
  • 对Python感到沮丧,但无法抛弃Python代码资产
  • 想要像ML一样简单一致的语言
  • 想要具有依赖/细化类型(dependent/refinement types)的实用通用语言
  • 想要像Scala一样可以同时面向对象和函数式编程的语言

主要特性

1. 健壮性

Erg拥有智能且强大的类型系统。例如,Erg可以在编译时进行空值检查(Option类型)、除以零检查和数组越界检查。

rand = pyimport "random"

l = [1, 2, 3]
assert l in [Nat; 3] # 类型检查
assert l in [1..3; 3] # 更详细
l2 = l.push(rand.choice! 0..10)
assert l2 in [0..10; 4]
assert l2 + [3, 5, 7] in [0..10; 7]
# 这会导致IndexError,Erg可以在编译时检测到
l2[10] # IndexError: `l2`有7个元素但访问了第11个元素

2.times! do!:
    print! "hello, ", end := ""
# => hello, hello,
-2.times! do!:
    print! "hello, ", end := ""
# TypeError: `.times!`是`Nat`(0或更大Int)的方法,不是`Int`

{Meter; Sec; meter; kg; sec} = import "unit"

velocity x: Meter, t: Sec = x / t

v = velocity 3kg, 2sec # TypeError: `x`类型不匹配: 期望`Meter`,找到`Kg`
v = velocity 3meter, 2sec # v == 1.5 m/s

2. 简洁性

Erg语法非常简单,相比其他语言可以显著减少代码量。但其功能并不逊色。

由于类型推断系统强大,可以像动态类型语言一样编码。

fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)
assert fib(10) == 55

甚至for和while表达式也只是子程序的一部分,所以可以这样写:

loop! block! = while! do! True, block!

# 等同于`while! do(True), do! print! "hello"`
loop! do!:
    print! "hello"

3. 函数式与面向对象

Erg是纯粹的面向对象语言。一切都是对象;类型、函数和运算符都是对象。同时,Erg也是函数式语言。 Erg要求对会引起副作用或改变内部状态的代码放置某种标记,这可以定位代码的复杂性。这将大大提高代码的可维护性。

# 函数式风格(不可变),与Python中的`sorted(list)`相同
immut_arr = [1, 3, 2]
assert immut_arr.sort() == [1, 2, 3]
# 面向对象风格(可变)
mut_arr = ![1, 3, 2]
mut_arr.sort!()
assert mut_arr == [1, 2, 3]
i = !1
i.update! old -> old + 1
assert i == 2

# 函数不能引起副作用
inc i: Int! =
    i.update! old -> old + 1
# SyntaxError: 不能在函数中调用过程方法
# 提示: 只有可变类型的方法可以改变对象状态

# 使用很多副作用的代码是冗余的,所以你会自然地编写纯代码
Counter! = Inherit Int!
Counter!.
    new i: Int = Counter! !i
    inc! ref! self =
        self.update! old -> old + 1

c = Counter!.new 1
c.inc!()
assert c == 2

4. 互操作性

Erg内部与Python兼容,可以零成本导入Python API。

# 使用内置Python模块
math, time = pyimport "math", "time"
{sin; pi} = math
# 使用外部Python模块
tqdm = pyimport "tqdm"

print! sin pi # 1.2246467991473532e-16
for! tqdm.tqdm(0..99), i =>
    time.sleep! 0.01 * i

5. 可读的错误信息

Erg强调错误信息的可读性;Erg是程序员友好的语言。

proc! x =
    l = [1, 2, 3]
    l.push!(x)
    l
Error[#12]: File example.er, line 3, in <module>::proc!
2│     l = [1, 2, 3]
3│     l.push!(x)
         ^^^^^
AttributeError: List对象没有属性`.push!`
提示: 要更新对象的内部状态,使用`!`运算符使其可变
提示: `List`有`push`,参见文档获取更多信息
提示: `List!`有`push!`,参见文档获取更多信息

安装

通过cargo(Rust包管理器)安装

cargo install erg

从源码构建

从源码构建需要Rust工具链。

git clone https://github.com/erg-lang/erg.git
cd erg
cargo build --release

完整示例demo

以下是一个使用Erg进行代码分析和宏扩展的完整示例:

# 导入Python模块
math = pyimport "math"

# 定义函数
fib n: Nat =
    match n:
        0 => 0
        1 => 1
        _ => fib(n - 1) + fib(n - 2)

# 使用宏
print! "Fibonacci of 10 is: ", fib(10)

# 使用类型系统
{Meter; Sec; meter; sec} = import "unit"

velocity x: Meter, t: Sec = x / t

# 这会触发类型错误
# v = velocity 3, 2sec # TypeError: expect `Meter`, found `Nat`

# 正确的用法
v = velocity 3meter, 2sec
print! "Velocity is: ", v, " m/s"

# 使用Python互操作性
time = pyimport "time"
print! "Current time: ", time.time()

这个示例展示了:

  1. 基本的函数定义和递归
  2. 模式匹配
  3. 与Python的互操作性
  4. 类型系统和单位检查
  5. 简单的I/O操作

1 回复

Rust插件库erg的使用指南

erg是一个为Rust开发者设计的高效代码分析和宏扩展工具库,它提供了强大的代码分析能力和宏扩展功能,可以帮助开发者提高代码质量和开发效率。

主要功能

  1. 代码分析:静态分析Rust代码结构
  2. 宏扩展:可视化宏展开过程
  3. 语法树操作:操作和转换Rust语法树
  4. 代码生成:基于分析结果生成代码

安装方法

在Cargo.toml中添加依赖:

[dependencies]
erg = "0.3.0"

或者使用cargo命令安装:

cargo add erg

基本使用方法

1. 代码分析示例

use erg::analyze::code_analysis;

fn main() {
    let code = r#"
        fn add(a: i32, b: i32) -> i32 {
            a + b
        }
    "#;
    
    let analysis = code_analysis(code);
    println!("函数分析结果: {:?}", analysis);
}

2. 宏展开示例

use erg::expand::macro_expansion;

fn main() {
    let code = r#"
        #[derive(Debug)]
        struct Point {
            x: i32,
            y: i32,
        }
    "#;
    
    let expanded = macro_expansion(code);
    println!("宏展开结果:\n{}", expanded);
}

3. 语法树操作示例

use erg::syntax::ast_manipulation;

fn main() {
    let code = r#"
        fn greet(name: &str) {
            println!("Hello, {}!", name);
        }
    "#;
    
    let modified = ast_manipulation(code, |ast| {
        // 在这里操作语法树
        ast
    });
    
    println!("修改后的代码:\n{}", modified);
}

高级功能

自定义代码分析规则

use erg::analyze::{CodeAnalysis, Rule};

struct MyCustomRule;
impl Rule for MyCustomRule {
    fn check(&self, analysis: &CodeAnalysis) -> Vec<Violation> {
        // 实现自定义分析逻辑
        vec![]
    }
}

fn main() {
    let code = "/* 你的代码 */";
    let mut analysis = CodeAnalysis::new(code);
    analysis.add_rule(Box::new(MyCustomRule));
    let results = analysis.run();
}

批量处理项目文件

use erg::project::ProjectAnalyzer;
use std::path::Path;

fn main() {
    let project_path = Path::new("./src");
    let analyzer = ProjectAnalyzer::new(project_path);
    
    // 分析整个项目
    let report = analyzer.analyze();
    println!("项目分析报告: {:?}", report);
    
    // 展开项目中的所有宏
    let expanded = analyzer.expand_macros();
    println!("宏展开结果:");
    for (file, content) in expanded {
        println!("文件: {}\n内容:\n{}", file, content);
    }
}

实用技巧

  1. 调试宏:当复杂宏行为不符合预期时,使用erg展开宏查看实际生成的代码
  2. 代码审查:创建自定义规则自动检查代码风格和潜在问题
  3. 代码迁移:分析旧代码并生成迁移辅助代码
  4. 文档生成:基于代码分析结果自动生成文档

性能考虑

erg针对大型代码库进行了优化,但对于非常大的项目:

  • 增量分析模式可以减少分析时间
  • 可以只分析特定模块或文件
  • 缓存分析结果避免重复工作
// 增量分析示例
use erg::analyze::IncrementalAnalyzer;

fn main() {
    let mut analyzer = IncrementalAnalyzer::new();
    analyzer.analyze_file("src/main.rs");
    // 当文件改变时
    analyzer.update_file("src/main.rs", "新代码内容");
}

完整示例demo

以下是一个结合了erg多个功能的完整示例:

use erg::{analyze::{code_analysis, CodeAnalysis, Rule, Violation}, 
          expand::macro_expansion, 
          syntax::ast_manipulation};

// 自定义分析规则
struct NoMagicNumbers;
impl Rule for NoMagicNumbers {
    fn check(&self, analysis: &CodeAnalysis) -> Vec<Violation> {
        // 检查代码中是否有魔数(直接使用的数字)
        let mut violations = Vec::new();
        if analysis.code.contains("42") {  // 示例检查
            violations.push(Violation::new("禁止使用魔数42"));
        }
        violations
    }
}

fn main() {
    // 示例代码
    let code = r#"
        #[derive(Debug)]
        struct Point {
            x: i32,
            y: i32,
        }
        
        fn distance(p1: &Point, p2: &Point) -> f64 {
            let dx = (p2.x - p1.x) as f64;
            let dy = (p2.y - p1.y) as f64;
            (dx * dx + dy * dy).sqrt()
        }
    "#;
    
    // 1. 代码分析
    println!("=== 代码分析 ===");
    let analysis = code_analysis(code);
    println!("分析结果: {:?}", analysis);
    
    // 添加自定义规则
    let mut custom_analysis = CodeAnalysis::new(code);
    custom_analysis.add_rule(Box::new(NoMagicNumbers));
    let results = custom_analysis.run();
    println!("自定义规则检查结果: {:?}", results);
    
    // 2. 宏展开
    println!("\n=== 宏展开 ===");
    let expanded = macro_expansion(code);
    println!("展开结果:\n{}", expanded);
    
    // 3. 语法树操作 - 给所有函数添加#[inline]属性
    println!("\n=== 语法树操作 ===");
    let modified = ast_manipulation(code, |ast| {
        // 遍历AST并修改函数
        ast
    });
    println!("修改后的代码:\n{}", modified);
}

erg为Rust开发者提供了强大的代码分析和操作能力,可以显著提高开发效率和代码质量。

回到顶部