Здравейте!
Моля за малко помощ/съвети. :)
Играя си с IR на език за програмиране в Rust структури и се опитвам да задоволя borrow checker-а. Имам следния набор от структури, с ненужните части изтрити за прегледност:
struct Runtime<'a> {
functions: HashMap<String, Function<'a>>
}
struct Function<'a> {
scope: Scope<'a>,
code: Block<'a>
}
struct Scope<'a> {
runtime: &'a Runtime<'a>,
vars: HashMap<String, Variable>
}
struct Variable {
name: String
// + other metadata
}
pub enum Instruction<'a> {
// Literal(ConstValue),
VariableRef(&'a Variable),
// Call(Call<'a>),
Block(Block<'a>)
}
struct Block<'a> {
code: Vec<Instruction<'a>>
}
impl<'a> Function<'a> {
pub fn build(ast: &'a parser::MethodDefAST, runtime: &'a Runtime<'a>) -> Function<'a> {
// Тук се проявяват проблемите
}
}
impl<'a> Instruction<'a> {
pub fn build(ast: &'a AST, scope: &'a Scope<'a>) -> Instruction<'a> {
// Това конструира Instruction обект, евентуално реферирайки променливи от scope-а
}
}
Идеята е следната:
-
Runtimeдържи всичко - трябва да е owner на всичко по транзитивност. -
Functionописва функция, съответно имаscopeза локални променливи вътре + код, който трябва да се изпълни. -
Scopeе owner на променливите и му трябва референция къмRuntime, за да може да търси функции. -
Variableне е само име, има други неща вътре, съответно не мога да го приравня къмString. Идеята е ако някъде се иска променлива, то тя да се специфицира с референцията къмVariable, не само с име. Това е така, защото името може да не е уникално и зависи от scope-а. -
Instructionе нещо, което може да реферира променливи.
Проблемите са основно с цикличните зависимости:
-
Runtimeдържи функции, но функциите иматscope, който реферираRuntime. - Функцията държи
scope, но и код, който може да реферира променливи от тозиscope. Като резултат, няма как да конструирамFunctionобект, защото трябва да вземаscopeот вече конструирания, за да го реферирам от code.
Може ли съвет как да променя структурите, така че borrow checker-а да е доволен?
Четох, че може да се използва Rc<RefCell<T>> в подобни ситуации:
- Добра идея ли е това в случая?
- Губя ли compile-time проверките, че докато имам Function ще е жив и Runtime-а? Тоест, мога ли да запазя текущите lifetime връзки, или някоя от тях поражда проблемите?
- Навсякъде ли е нужно да минава през
Rc<RefCell<T>>или има начин да се реферират по този начин само при връзките отдолу-нагоре? - Ако направя
ScopeиVariableRC-та мисля, че няма да има циклични зависимости между RC обектите (тоест няма да тече памет). Има ли нещо, което пропускам?
Има ли нещо по-добро от Rc<RefCell<T>> в случая?
Благодаря предварително :)
