Rust插件库erg的使用,为Rust开发者提供高效代码分析和宏扩展功能
Rust插件库erg的使用,为Rust开发者提供高效代码分析和宏扩展功能
Erg编程语言
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()
这个示例展示了:
- 基本的函数定义和递归
- 模式匹配
- 与Python的互操作性
- 类型系统和单位检查
- 简单的I/O操作
1 回复
Rust插件库erg的使用指南
erg是一个为Rust开发者设计的高效代码分析和宏扩展工具库,它提供了强大的代码分析能力和宏扩展功能,可以帮助开发者提高代码质量和开发效率。
主要功能
- 代码分析:静态分析Rust代码结构
- 宏扩展:可视化宏展开过程
- 语法树操作:操作和转换Rust语法树
- 代码生成:基于分析结果生成代码
安装方法
在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);
}
}
实用技巧
- 调试宏:当复杂宏行为不符合预期时,使用erg展开宏查看实际生成的代码
- 代码审查:创建自定义规则自动检查代码风格和潜在问题
- 代码迁移:分析旧代码并生成迁移辅助代码
- 文档生成:基于代码分析结果自动生成文档
性能考虑
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开发者提供了强大的代码分析和操作能力,可以显著提高开发效率和代码质量。