use std;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use crate::hir;
use crate::score::*;
use crate::score::{ScoreBoard, ScoreContext};
use crate::ty::Ty;
use crate::typeck::TypeckContext;
use moore_common::score::{NodeStorage, Result};
use moore_common::NodeId;
pub enum LazyNode<F> {
Running,
Pending(F),
}
impl<F> fmt::Debug for LazyNode<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
LazyNode::Running => write!(f, "running"),
LazyNode::Pending(_) => write!(f, "pending"),
}
}
}
pub struct LazyPhaseTable<'sb, 'ast: 'sb, 'ctx: 'sb> {
pub sb: &'sb ScoreBoard<'ast, 'ctx>,
pub hir: LazyPhase<LazyHirTable<'sb, 'ast, 'ctx>>,
pub typeck: RefCell<LazyTypeckTable<'sb, 'ast, 'ctx>>,
pub typeval: RefCell<LazyTypevalTable<'sb, 'ast, 'ctx>>,
}
impl<'sb, 'ast, 'ctx> LazyPhaseTable<'sb, 'ast, 'ctx> {
pub fn new(sb: &'sb ScoreBoard<'ast, 'ctx>) -> LazyPhaseTable<'sb, 'ast, 'ctx> {
LazyPhaseTable {
sb: sb,
hir: LazyPhase::new(),
typeck: RefCell::new(HashMap::new()),
typeval: RefCell::new(HashMap::new()),
}
}
}
pub struct LazyPhase<T> {
pub table: RefCell<T>,
}
impl<T: Default> LazyPhase<T>
where
T: Default,
{
pub fn new() -> LazyPhase<T> {
LazyPhase {
table: RefCell::new(Default::default()),
}
}
pub fn schedule<I, F>(&self, id: I, f: F)
where
T: NodeStorage<I, Node = LazyNode<F>>,
{
self.table.borrow_mut().set(id, LazyNode::Pending(f));
}
pub fn run<'lazy, 'sb, 'ast, 'ctx, I, R>(
&self,
id: I,
ctx: &ScoreContext<'lazy, 'sb, 'ast, 'ctx>,
) -> Result<R>
where
I: Copy + fmt::Debug,
T: NodeStorage<
I,
Node = LazyNode<
Box<for<'a, 'b> Fn(&'a ScoreContext<'b, 'sb, 'ast, 'ctx>) -> Result<R> + 'sb>,
>,
>,
{
let task = self.table.borrow_mut().set(id, LazyNode::Running);
match task {
Some(LazyNode::Pending(f)) => f(ctx),
Some(LazyNode::Running) => panic!("recursion when running task for {:?}", id),
None => panic!("no task scheduled for {:?}", id),
}
}
}
pub type LazyHir<'sb, 'ast, 'ctx, R> =
Box<for<'a, 'b> Fn(&'a ScoreContext<'b, 'sb, 'ast, 'ctx>) -> Result<R> + 'sb>;
pub type LazyTypeck<'sb, 'ast, 'ctx> =
Box<for<'a, 'b, 'c> Fn(&'a TypeckContext<'b, 'c, 'sb, 'ast, 'ctx>) -> Result<()> + 'sb>;
pub type LazyTypeval<'sb, 'ast, 'ctx> =
Box<for<'a, 'b, 'c> Fn(&'a TypeckContext<'b, 'c, 'sb, 'ast, 'ctx>) -> Result<&'ctx Ty> + 'sb>;
node_storage!(LazyHirTable<'sb, 'ast, 'ctx> where ('ast: 'sb, 'ctx: 'sb):
subtype_inds: SubtypeIndRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::SubtypeInd>>,
exprs: ExprRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Expr>>,
aggregates: AggregateRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Aggregate>>,
const_decls: ConstDeclRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Decl<hir::ConstDecl>>>,
signal_decls: SignalDeclRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Decl<hir::SignalDecl>>>,
var_decls: VarDeclRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Decl<hir::VarDecl>>>,
file_decls: FileDeclRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Decl<hir::FileDecl>>>,
type_decls: TypeDeclRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::TypeDecl>>,
wait_stmts: WaitStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::WaitStmt>>>,
assert_stmts: AssertStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::AssertStmt>>>,
report_stmts: ReportStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::ReportStmt>>>,
sig_assign_stmts: SigAssignStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::SigAssignStmt>>>,
var_assign_stmts: VarAssignStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::VarAssignStmt>>>,
call_stmt: CallStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::CallStmt>>>,
if_stmt: IfStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::IfStmt>>>,
case_stmt: CaseStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::CaseStmt>>>,
loop_stmt: LoopStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::LoopStmt>>>,
nexit_stmt: NexitStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::NexitStmt>>>,
return_stmt: ReturnStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::ReturnStmt>>>,
null_stmt: NullStmtRef => LazyNode<LazyHir<'sb, 'ast, 'ctx, hir::Stmt<hir::NullStmt>>>,
);
impl<'sb, 'ast, 'ctx> Default for LazyHirTable<'sb, 'ast, 'ctx> {
fn default() -> LazyHirTable<'sb, 'ast, 'ctx> {
LazyHirTable::new()
}
}
pub type LazyTypeckTable<'sb, 'ast, 'ctx> = HashMap<NodeId, LazyNode<LazyTypeck<'sb, 'ast, 'ctx>>>;
pub type LazyTypevalTable<'sb, 'ast, 'ctx> =
HashMap<NodeId, LazyNode<LazyTypeval<'sb, 'ast, 'ctx>>>;