Я пытаюсь манипулировать АСТ в Rust. Будет много манипуляций, и я хочу, чтобы мои деревья были неизменными, поэтому для экономии времени все ссылки будут Rc
s.
Мои узлы дерева будут выглядеть так:
enum Condition {
Equals(Rc<Expression>, Rc<Expression>),
LessThan(Rc<Expression>, Rc<Expression>),
...
}
enum Expression {
Plus(Rc<Expression>, Rc<Expression>),
...
}
Я хочу заменить случайный node данного типа на другой node того же типа. Чтобы выполнить родовые операции с деревьями, я сделал черту:
trait AstNode {
fn children(&self) -> Vec<Rc<AstNode>>;
}
И все узлы реализуют это. Это позволяет мне ходить по дереву без необходимости разрушать каждый тип node для каждой операции, просто называя children()
.
Я также хочу клонировать node, обновляя только один из его дочерних элементов, и оставляя другие на месте. Предположим, что я смог генерировать узлы нужного конкретного типа (и я счастлив, что программа впадает в панику, если я ошибаюсь). Я добавлю следующий метод к признаку:
trait AstNode {
fn clone_with_children(&self, new_children: Vec<Rc<AstNode>>) -> Self
where Self: Sized;
}
Мой план состоит в том, чтобы вернуть детей, возвращаемых childen()
, заменить один из них и вызвать clone_with_children()
для создания node того же варианта перечисления, но с заменой одного node.
Моя проблема заключается в том, как написать clone_with_children()
.
Мне нужно отключить Rc<AstNode>
до Rc<Expression>
(или что у вас есть), сохраняя при этом refcount внутри Rc
тем же, но ни одна из библиотек downcasting, которые я нашел, похоже, не может это сделать.
Я хочу, чтобы это было возможно, или я должен делать это совершенно по-другому?