feat: SCC analysis (thunk capture WIP)
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use lru::LruCache;
|
||||
use priority_queue::PriorityQueue;
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::error::Result;
|
||||
use crate::eval::Evaluate;
|
||||
use crate::ir::{Downgraded, Ir};
|
||||
use crate::ty::internal as i;
|
||||
use crate::ir::{Dep, Downgraded, Ir, SccNode};
|
||||
use crate::ty::internal::{self as i, ThunkRef};
|
||||
use crate::ty::public::Value;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -18,40 +17,63 @@ type ThunkIdx = usize;
|
||||
type EnvIdx = usize;
|
||||
|
||||
pub struct Engine {
|
||||
thunks: Box<[Ir]>,
|
||||
pub thunks: Box<[Ir]>,
|
||||
pub func_offset: usize,
|
||||
pub func_deps: Vec<HashSet<Dep>>,
|
||||
tasks: PriorityQueue<CompileTask, usize>,
|
||||
lru: LruCache<(ThunkIdx, EnvIdx), i::Value>,
|
||||
}
|
||||
|
||||
pub fn eval(downgraded: Downgraded) -> Result<Value> {
|
||||
let mut engine = Engine::new(downgraded.thunks, downgraded.func_offset);
|
||||
engine
|
||||
.eval()
|
||||
.map(|mut val| {
|
||||
Ok(val
|
||||
.force(&mut engine)?
|
||||
.to_public(&engine, &mut HashSet::new()))
|
||||
})?
|
||||
let mut engine = Engine::new(downgraded.thunks, downgraded.func_offset, downgraded.func_deps);
|
||||
engine.eval(downgraded.graph)
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn new(thunks: Box<[Ir]>, func_offset: usize) -> Self {
|
||||
pub fn new(thunks: Box<[Ir]>, func_offset: usize, func_deps: Vec<HashSet<Dep>>) -> Self {
|
||||
Self {
|
||||
lru: LruCache::new(thunks.len().try_into().unwrap()),
|
||||
tasks: PriorityQueue::new(),
|
||||
thunks,
|
||||
func_offset,
|
||||
tasks: PriorityQueue::new(),
|
||||
func_deps
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(&mut self) -> Result<i::Value> {
|
||||
self.thunks.last().unwrap().clone().eval(self, &mut VmEnv::new())
|
||||
pub fn eval(&mut self, graph: Vec<SccNode>) -> Result<Value> {
|
||||
let mut env = VmEnv::new();
|
||||
let last = graph.last().unwrap().members[0];
|
||||
for SccNode { members, .. } in graph.into_iter() {
|
||||
// TODO:
|
||||
assert!(members.len() == 1);
|
||||
for member in members.into_iter() {
|
||||
let val = self.thunks[member].clone().eval(self, &mut env)?;
|
||||
env.insert_cache(member, val);
|
||||
}
|
||||
}
|
||||
env.lookup_cache(last, |_| unreachable!())
|
||||
.map(|mut val| Ok(val.force(self, &mut env)?.to_public(self, &mut HashSet::new())))?
|
||||
}
|
||||
|
||||
pub fn eval_thunk(&mut self, idx: usize, env: &mut VmEnv) -> Result<i::Value> {
|
||||
self.thunks[idx].clone().eval(self, env)
|
||||
}
|
||||
|
||||
pub fn eval_func_deps(&mut self, idx: usize, env: &mut VmEnv) -> Result<()> {
|
||||
for dep in self.func_deps[idx - self.func_offset].clone() {
|
||||
match dep {
|
||||
Dep::Arg(idx) => {
|
||||
if let i::Value::Thunk(ThunkRef { idx }) = env.lookup_arg(idx) {
|
||||
let val = self.thunks[idx].clone().eval(self, env)?;
|
||||
env.insert_cache(idx, val)
|
||||
}
|
||||
},
|
||||
Dep::Thunk(idx) =>{
|
||||
let val = self.thunks[idx].clone().eval(self, env)?;
|
||||
env.insert_cache(idx, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
enum Thunk {
|
||||
|
||||
Reference in New Issue
Block a user