ugh, variance...

This commit is contained in:
numzero 2025-04-19 12:03:10 +03:00
parent c42a7b2251
commit 6c1e6d6bfa

View File

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{cell::RefCell, collections::HashMap};
use crate::ast;
@ -53,27 +53,62 @@ struct Call {
args: Vec<Expression>,
}
#[derive(Debug)]
struct BuildContext<'a> {
parent: Option<&'a mut BuildContext<'a>>,
#[derive(Debug, Clone, Default)]
struct Scope {
upvalues: Vec<(ast::Ident, Ident)>,
scope: HashMap<ast::Ident, Ident>,
}
impl Scope {
fn new_toplevel() -> Self {
Self {
upvalues: vec![("_ENV".to_string(), Ident::Local(0))],
scope: [("_ENV".to_string(), Ident::Upvalue(0))]
.into_iter()
.collect(),
}
}
}
#[derive(Debug)]
struct BuildContext<'a> {
parent: Option<&'a BuildContext<'a>>, // mustn't be &mut because of variance
scope: RefCell<Scope>,
}
impl BuildContext<'_> {
fn request(&mut self, name: &ast::Ident) -> Option<Ident> {
if let Some(ident) = self.scope.get(name) {
fn request(&self, name: &ast::Ident) -> Option<Ident> {
let mut scope = self.scope.borrow_mut();
if let Some(ident) = scope.scope.get(name) {
return Some(*ident);
}
if let Some(ident) = self.parent.as_mut()?.request(name) {
let index = self.upvalues.len();
self.upvalues.push((name.clone(), ident));
return Some(Ident::Upvalue(index));
if let Some(ident) = self.parent.as_ref()?.request(name) {
let index = scope.upvalues.len();
scope.upvalues.push((name.clone(), ident));
let ident = Ident::Upvalue(index);
scope.scope.insert(name.clone(), ident);
return Some(ident);
}
None
}
}
pub fn build(code: ast::Function) -> Function {
fn build_in_scope(parent: &BuildContext<'_>, code: ast::Function) -> Function {
let scope = BuildContext {
parent: Some(parent),
scope: Default::default(),
};
if false {
build_in_scope(&scope, code.clone());
build_in_scope(&scope, code.clone());
}
todo!()
}
pub fn build(code: ast::Function) -> Function {
let mut root = BuildContext {
parent: None,
scope: RefCell::new(Scope::new_toplevel()),
};
build_in_scope(&mut root, code)
}