mod ast;
mod program;
mod scope_state;
mod visitor;
use visitor::*;
use self::scope_state::ScopeState;
use crate::{CompilerState, Pass};
use leo_ast::{CallGraph, CompositeGraph, NetworkName, ProgramVisitor};
use leo_errors::Result;
use snarkvm::prelude::{CanaryV0, MainnetV0, Network, TestnetV0};
use indexmap::{IndexMap, IndexSet};
#[derive(Clone)]
pub struct TypeCheckingInput {
pub max_array_elements: usize,
pub max_mappings: usize,
pub max_functions: usize,
pub max_inputs: usize,
pub max_outputs: usize,
}
impl TypeCheckingInput {
pub fn new(network: NetworkName) -> Self {
let (max_array_elements, max_mappings, max_functions, max_inputs, max_outputs) = match network {
NetworkName::MainnetV0 => (
MainnetV0::MAX_ARRAY_ELEMENTS,
MainnetV0::MAX_MAPPINGS,
MainnetV0::MAX_FUNCTIONS,
MainnetV0::MAX_INPUTS,
MainnetV0::MAX_OUTPUTS,
),
NetworkName::TestnetV0 => (
TestnetV0::MAX_ARRAY_ELEMENTS,
TestnetV0::MAX_MAPPINGS,
TestnetV0::MAX_FUNCTIONS,
TestnetV0::MAX_INPUTS,
TestnetV0::MAX_OUTPUTS,
),
NetworkName::CanaryV0 => (
CanaryV0::MAX_ARRAY_ELEMENTS,
CanaryV0::MAX_MAPPINGS,
CanaryV0::MAX_FUNCTIONS,
CanaryV0::MAX_INPUTS,
CanaryV0::MAX_OUTPUTS,
),
};
Self { max_array_elements, max_mappings, max_functions, max_inputs, max_outputs }
}
}
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 composite_names = state
.symbol_table
.iter_records()
.map(|(loc, _)| loc.clone())
.chain(state.symbol_table.iter_structs().map(|(loc, _)| loc.clone()))
.collect();
let function_names = state.symbol_table.iter_functions().map(|(loc, _)| loc.clone()).collect();
let ast = std::mem::take(&mut state.ast);
state.composite_graph = CompositeGraph::new(composite_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_composites: IndexSet::new(),
conditional_scopes: Vec::new(),
limits: input,
async_block_id: None,
};
visitor.visit_program(ast.as_repr());
visitor.state.handler.last_err()?;
visitor.state.composite_graph.retain_nodes(&visitor.used_composites);
visitor.state.ast = ast;
Ok(())
}
}