[英]How to create self-referential AST in Rust?
Let's imagine we have a very simple AST for programming language with only functions and calls假设我们有一个非常简单的编程语言 AST,只有函数和调用
use std::sync::Arc;
struct Function {
pub body: Vec<Call>
}
struct Call {
pub function: Arc<Function>
}
Now we want to recursively call functions:现在我们要递归调用函数:
let f = Arc::new(Function { body: vec![Call {function: f.clone()}] })
// Doesn't work, as we haven't created Arc yet
let mut f = Arc::new(Function { body: vec![] });
f.body.push(Call { function: f.clone() })
// Doesn't work, because Arc has immutable data
The problem can be solved using Arc<Mutex<_>>
or Arc<RwLock<_>>
in Call
:这个问题可以在
Call
中使用Arc<Mutex<_>>
或Arc<RwLock<_>>
来解决:
use std::sync::{Arc, RwLock}
struct Call {
pub function: Arc<RwLock<Function>>
}
And then creating with:然后创建:
let f = Arc::new(RwLock::new(Function { body: vec![] }));
f.write().unwrap().body.push(Call { function: f.clone() })
But now you need to always write f.write().unwrap()
or f.read().unwrap()
everywhere, even though function is mutable only on construction .但是现在您需要始终在任何地方编写
f.write().unwrap()
或f.read().unwrap()
,即使 function仅在构造时可变。
Can you do something better than this?你能做比这更好的事吗?
Use Weak
for the parent pointer.对父指针使用
Weak
k。 You need to do that anyway to allow for proper destruction.无论如何,您都需要这样做才能进行适当的销毁。 Then use
Arc::new_cyclic()
:然后使用
Arc::new_cyclic()
:
use std::sync::{Arc, Weak};
struct Function {
pub body: Vec<Call>,
}
struct Call {
pub function: Weak<Function>,
}
let f = Arc::new_cyclic(|f| Function {
body: vec![Call {
function: Weak::clone(f),
}],
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.