use crate::{
hir::{self, Hir},
parse::Sources,
ty::{Gcx, GcxMut},
};
use solar_ast as ast;
use solar_data_structures::{
index::{Idx, IndexVec},
map::FxHashMap,
};
use solar_interface::{Session, diagnostics::DiagCtxt};
mod lower;
mod linearize;
pub(crate) mod resolve;
pub(crate) use resolve::{Res, SymbolResolver};
#[instrument(name = "ast_lowering", level = "debug", skip_all)]
pub(crate) fn lower(mut gcx: GcxMut<'_>) {
let mut lcx = LoweringContext::new(gcx.get());
lcx.lower_sources();
lcx.collect_exports();
lcx.perform_imports();
lcx.collect_contract_declarations();
lcx.resolve_base_contracts();
lcx.linearize_contracts();
lcx.assign_constructors();
let mut rcx = resolve::ResolveContext::new(lcx);
rcx.resolve_symbols();
rcx.resolve_base_args();
let mut lcx = rcx.lcx;
lcx.shrink_to_fit();
let gcx = gcx.get_mut();
(gcx.hir, gcx.symbol_resolver) = lcx.finish();
}
struct LoweringContext<'gcx> {
sess: &'gcx Session,
arena: &'gcx hir::Arena,
hir: Hir<'gcx>,
sources: &'gcx Sources<'gcx>,
hir_to_ast: FxHashMap<hir::ItemId, &'gcx ast::Item<'gcx>>,
current_source_id: hir::SourceId,
current_contract_id: Option<hir::ContractId>,
resolver: SymbolResolver<'gcx>,
next_id: IdCounter,
}
impl<'gcx> LoweringContext<'gcx> {
fn new(gcx: Gcx<'gcx>) -> Self {
Self {
sess: gcx.sess,
arena: gcx.arena(),
sources: &gcx.sources,
hir: Hir::new(),
current_source_id: hir::SourceId::MAX,
current_contract_id: None,
hir_to_ast: FxHashMap::default(),
resolver: SymbolResolver::new(&gcx.sess.dcx),
next_id: IdCounter::new(),
}
}
#[inline]
fn dcx(&self) -> &'gcx DiagCtxt {
&self.sess.dcx
}
#[instrument(level = "debug", skip_all)]
fn shrink_to_fit(&mut self) {
self.hir.shrink_to_fit();
}
#[instrument(name = "drop_lcx", level = "debug", skip_all)]
fn finish(self) -> (Hir<'gcx>, SymbolResolver<'gcx>) {
{
let this = self;
(this.hir, this.resolver)
}
}
}
struct IdCounter {
counter: std::cell::Cell<usize>,
}
impl IdCounter {
fn new() -> Self {
Self { counter: std::cell::Cell::new(0) }
}
#[inline]
fn next<I: Idx>(&self) -> I {
I::from_usize(self.next_usize())
}
#[inline]
fn next_usize(&self) -> usize {
let x = self.counter.get();
self.counter.set(x + 1);
x
}
}
#[inline]
#[track_caller]
fn get_two_mut_idx<I: Idx, T>(sl: &mut IndexVec<I, T>, idx_1: I, idx_2: I) -> (&mut T, &mut T) {
get_two_mut(&mut sl.raw, idx_1.index(), idx_2.index())
}
#[inline]
#[track_caller]
fn get_two_mut<T>(sl: &mut [T], idx_1: usize, idx_2: usize) -> (&mut T, &mut T) {
sl.get_disjoint_mut([idx_1, idx_2]).unwrap().into()
}