mod expression;
mod program;
mod scope_state;
mod statement;
mod visitor;
use visitor::*;
use self::scope_state::ScopeState;
use crate::{CallGraph, CompilerState, Pass, StructGraph};
use leo_ast::ProgramVisitor;
use leo_errors::Result;
use indexmap::{IndexMap, IndexSet};
pub struct TypeCheckingInput {
pub max_array_elements: usize,
pub max_mappings: usize,
pub max_functions: usize,
}
pub struct TypeChecking;
impl Pass for TypeChecking {
type Input = TypeCheckingInput;
type Output = ();
const NAME: &'static str = "TypeChecking";
fn do_pass(input: Self::Input, state: &mut CompilerState) -> Result<Self::Output> {
let struct_names = state
.symbol_table
.iter_records()
.map(|(loc, _)| loc.name)
.chain(state.symbol_table.iter_structs().map(|(name, _)| name))
.collect();
let function_names = state.symbol_table.iter_functions().map(|(loc, _)| loc.name).collect();
let ast = std::mem::take(&mut state.ast);
state.struct_graph = StructGraph::new(struct_names);
state.call_graph = CallGraph::new(function_names);
let mut visitor = TypeCheckingVisitor {
state,
scope_state: ScopeState::new(),
async_function_input_types: IndexMap::new(),
async_function_callers: IndexMap::new(),
used_structs: IndexSet::new(),
conditional_scopes: Vec::new(),
limits: input,
};
visitor.visit_program(ast.as_repr());
visitor.state.handler.last_err().map_err(|e| *e)?;
visitor.state.struct_graph.retain_nodes(&visitor.used_structs);
visitor.state.ast = ast;
Ok(())
}
}