1 个不稳定版本
使用旧的 Rust 2015
0.1.0 | 2016年8月26日 |
---|
#1564 in 开发工具
2KB
rabbot
Rabbot 生成抽象绑定树(ABT)的接口。它是 SML 的 Abbot 的 Rust 版本。
什么是 ABT?
抽象绑定树是一种类似于抽象语法树的数据结构,但它允许你愉快且正确地处理符号的声明和绑定。为了说明这一点,让我们考虑一个简单伪语言的语法树。对于表达式 2 + 1
,这将产生一个语法树 Plus(Number(2), Number(1))
。对于表达式 let x = 1 in x + 2
,这将产生 Let(Var("x"), Number(1), Plus(Var("x"), Number(2))
。对于这些示例,使用正常的抽象语法树就足够了。
然而,如果我们引入多个同名绑定,我们就会遇到麻烦。例如,在表达式 let x = 1 in (let x = 2 in x) + x
中,我们现在需要某种作用域分析的概念。哪个 x
实例指的是什么?ABTs 通过提供处理变量绑定和替换的构造来消除这个问题。前面的表达式大致翻译为 Let(1, x . (Let(2, x . x) + x))
,其中点 .
表示绑定点。更多信息请参阅 Bob Harper 的 《程序设计语言的实用基础》,第一章。
Rabbot 做什么?
创建抽象语法的树的常用方法是定义一个枚举,其中每个分支对应于语法的一个部分,例如。
enum Expression {
Number(i32),
Plus(Box<Expression>, Box<Expression>),
...
}
然而,ABTs 的工作方式不同。在核心上,ABT 是一个由一组操作符参数化的固定树数据结构,其中每个操作符描述了像 Number
或 Plus
这样的功能。有关数据类型的定义,请参阅 rabbot/src/abt.rs
。这使得您可以轻松地重用 ABT 结构来表示不同类型的程序,但实际使用时需要更多的样板代码和更多的代码。
为了减轻使用 ABTs 的冗长性,Rabbot 接受一个抽象绑定树的描述,并为程序员生成一个更简洁的接口。例如,可以在几行内实现带有佩亚诺数和其解释器的lambda演算。
#![feature(plugin, box_syntax)]
#![plugin(rabbot_plugin)]
#[macro_use] extern crate rabbot;
rabbot! {
sort Term {
Z,
S(Term),
Lam(Binding<Term> . Term),
App((Term, Term))
}
}
use rabbot::var::Var;
use term::*;
fn interpret(t: Term) -> Term {
match out(t) {
v @ View::Z | v @ View::Lam(_) => into(v),
View::S(t) => {
bind!(View::S{v} = out(interpret(t)));
into(View::S(v))
},
View::App((fun, arg)) => {
bind!(View::Lam{(var, body)} = out(interpret(fun)));
subst(arg, var, body)
},
View::Var(_) => unreachable!()
}
}
#[test]
fn test() {
let x = Var::new("x".to_string());
let term = into(View::App((
into(View::Lam((
x.clone(), into(View::S(into(View::Var(x.clone()))))))),
into(View::Z))));
println!("{:?}", interpret(term)); // prints S(Z)
}
注意事项
这仍在积极开发中,如果您想使用它,请与我联系(电子邮件:[email protected])。代码生成器作为一个编译器插件工作,因此只能在 nightly 版本上使用,尽管这不是一个硬性要求。