use crate::ast::Expression;
use crate::ast::LiteralTemplatePart;
use crate::ast::Module;
use crate::ast::ModuleItem;
use crate::ast::Node;
use crate::ast::Statement;
use crate::symbol::Scope;
use crate::symbol::ScopeType;
pub struct LifetimeAnalyser {}
impl LifetimeAnalyser {
fn process_variable(&mut self, scope: &Scope, name: &str) {
if let Some((decl_scope, symbol)) = scope.find_symbol_declaration(name) {
if let Some(decl_closure) = decl_scope.find_nearest_closure() {
if let Some(usage_closure) = scope.find_nearest_closure() {
if decl_closure != usage_closure {
decl_scope.borrow_mut().boxed_var_decls.insert(symbol);
let mut cur = usage_closure;
while cur != decl_scope {
if cur.typ == ScopeType::Closure {
cur.borrow_mut().boxed_var_captures.insert(symbol);
};
cur = cur.parent().unwrap();
}
};
};
};
};
}
fn analyse_expression(&mut self, expr: &Node<Expression>) {
match expr.stx.as_ref() {
Expression::Binary { left, right, .. } => {
self.analyse_expression(left);
self.analyse_expression(right);
}
Expression::BindMethod { arguments, .. } => {
for arg in arguments {
self.analyse_expression(arg);
}
}
Expression::Block { statements, result } => {
for stmt in statements {
self.analyse_statement(stmt);
}
if let Some(result) = result {
self.analyse_expression(result);
};
}
Expression::CallMethod {
object, arguments, ..
} => {
self.analyse_expression(object);
for arg in arguments {
self.analyse_expression(arg);
}
}
Expression::CallValue {
callee, arguments, ..
} => {
self.analyse_expression(callee);
for arg in arguments {
self.analyse_expression(arg);
}
}
Expression::Cast { value, .. } => {
self.analyse_expression(value);
}
Expression::Field { object, .. } => {
self.analyse_expression(object);
}
Expression::Index { object, index, .. } => {
self.analyse_expression(object);
self.analyse_expression(index);
}
Expression::If {
condition,
consequent,
alternate,
} => {
self.analyse_expression(condition);
self.analyse_expression(consequent);
if let Some(alternate) = alternate {
self.analyse_expression(alternate);
};
}
Expression::Closure { body, .. } => {
self.analyse_expression(body);
}
Expression::LiteralArray { entries } => {
for ent in entries {
self.analyse_expression(ent);
}
}
Expression::LiteralBoolean { .. } => {}
Expression::LiteralFloat { .. } => {}
Expression::LiteralInt { .. } => {}
Expression::LiteralNone { .. } => {}
Expression::LiteralObject { fields } => {
for (_, value) in fields {
self.analyse_expression(value);
}
}
Expression::LiteralTemplateExpr { parts } => {
for part in parts {
match part {
LiteralTemplatePart::Substitution(v) => {
self.analyse_expression(v);
}
LiteralTemplatePart::String(_) => {}
};
}
}
Expression::Unary { operand, .. } => {
self.analyse_expression(operand);
}
Expression::Var { name } => {
self.process_variable(&expr.scope, name);
}
}
}
fn analyse_statement(&mut self, stmt: &Node<Statement>) {
match stmt.stx.as_ref() {
Statement::Break => {}
Statement::Continue => {}
Statement::Expression { expression } => {
self.analyse_expression(expression);
}
Statement::FieldAssign { object, value, .. } => {
self.analyse_expression(object);
self.analyse_expression(value);
}
Statement::For { iterable, body, .. } => {
self.analyse_expression(iterable);
self.analyse_expression(body);
}
Statement::IndexAssign {
object,
index,
value,
..
} => {
self.analyse_expression(object);
self.analyse_expression(index);
self.analyse_expression(value);
}
Statement::Let { value, .. } => {
self.analyse_expression(value);
}
Statement::Loop { body } => {
self.analyse_expression(body);
}
Statement::Return { value } => {
if let Some(value) = value {
self.analyse_expression(value);
};
}
Statement::VarAssign { variable, value } => {
self.analyse_expression(value);
self.process_variable(&stmt.scope, &variable);
}
};
}
fn analyse_module_item(&mut self, item: &Node<ModuleItem>) {
match item.stx.as_ref() {
ModuleItem::Impl { methods, .. } => {
for (_, method) in methods {
self.analyse_expression(method);
}
}
ModuleItem::Statement { statement } => {
self.analyse_statement(statement);
}
};
}
pub fn analyse_lifetimes(&mut self, module: &Module) {
for item in module.items.iter() {
self.analyse_module_item(item);
}
}
}