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::LATEST_MAX_ARRAY_ELEMENTS(),
MainnetV0::MAX_MAPPINGS,
MainnetV0::MAX_FUNCTIONS,
MainnetV0::MAX_INPUTS,
MainnetV0::MAX_OUTPUTS,
),
NetworkName::TestnetV0 => (
TestnetV0::LATEST_MAX_ARRAY_ELEMENTS(),
TestnetV0::MAX_MAPPINGS,
TestnetV0::MAX_FUNCTIONS,
TestnetV0::MAX_INPUTS,
TestnetV0::MAX_OUTPUTS,
),
NetworkName::CanaryV0 => (
CanaryV0::LATEST_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: IndexSet<leo_ast::Location> =
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_count = function_names.iter().cloned().map(|n| (n, 0)).collect();
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,
};
ast.visit(
|program| visitor.visit_program(program),
|_library| {
},
);
visitor.state.handler.last_err()?;
visitor.used_composites.extend(visitor.state.symbol_table.iter_records().map(|(loc, _)| loc.clone()));
visitor.state.composite_graph.retain_nodes(&visitor.used_composites);
visitor.state.ast = ast;
Ok(())
}
}