#tree #abstract #binding #compiler-plugin

nightly rabbot-plugin

Rabbot 编译器插件

1 个不稳定版本

使用旧的 Rust 2015

0.1.0 2016年8月26日

#1564 in 开发工具

Apache-2.0/MIT

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 是一个由一组操作符参数化的固定树数据结构,其中每个操作符描述了像 NumberPlus 这样的功能。有关数据类型的定义,请参阅 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 版本上使用,尽管这不是一个硬性要求。

依赖关系