如何在Rust中动态构建具有不同数量参数的函数调用?

时间:2019-07-02 16:07:33

标签: function dynamic rust interpreter

如何获取函数自变量AST变体的向量,提取值并使用它们实例化函数调用?

我正在写一个评估某些表达式的解释器。一些表达式是函数调用。我很难弄清楚如何将AST转换为实际调用。 AST给了我函数名称和参数向量。我可以使用映射从名称中查找要调用的函数指针,但是将参数传递给函数指针是有问题的。

Rust没有splat运算符(参数扩展)。我可以将它们作为元组传递并使用参数的解构,但是我不知道如何将AST参数枚举变量的向量转换为具体类型的元组。

我不能简单地映射或循环AST参数以提取值并生成元组。

我可以使用嵌套元组来逐步构建异构列表:

fn prepend<I,T>(i: I, t: T) -> (I,T) { (i, t) }

fn foo() {
    let x = ();
    let x = prepend(1, x);
    let x = prepend(2.0, x);
    let x = prepend(true, x);
}

但这仅能起作用,因为x被遮蔽并且新绑定具有不同的类型。这行不通:

fn foo() {
    let mut x = ();
    x = prepend(1, x);
    x = prepend(2.0, x);
    x = prepend(true, x);
}

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

你不知道。 Rust是一种静态类型语言,您正在尝试执行非静态确定的操作。

相反,您的所有函数都需要接收一组参数,验证是否有正确数量的参数(以及类型,如果适合您的解释器),然后使用固定数量的参数调用适当的Rust函数:

// All of the panicking can be replaced by proper error handling.

enum Arg {
    Bool(bool),
    Int(i32),
}

impl Arg {
    fn into_bool(self) -> bool {
        match self {
            Arg::Bool(b) => b,
            _ => panic!("Not a bool"),
        }
    }

    fn into_int(self) -> i32 {
        match self {
            Arg::Int(i) => i,
            _ => panic!("Not an int"),
        }
    }
}

fn some_fn_wrapper(mut args: Vec<Arg>) {
    assert_eq!(args.len(), 3);

    let c = args.pop().unwrap();
    let b = args.pop().unwrap();
    let a = args.pop().unwrap();

    some_fn(a.into_bool(), b.into_int(), c.into_bool())
}

fn some_fn(_a: bool, _b: i32, _c: bool) {}

所有这些都将在运行时发生,因为您要创建一种高度动态的语言。

另请参阅: