device-driver-mir 2.2.0

Internal compiler crate for the device-driver toolkit
Documentation
use std::collections::HashSet;

use crate::{
    model::{Manifest, ObjectId},
    passes::{Assumption, Pass},
};
use device_driver_diagnostics::{
    Diagnostics, DynError,
    errors::{ExternInvalidBaseType, ExternInvalidSizeBits},
};

/// Checks if externs are fully specified
pub struct ExternValuesChecked;

impl Pass for ExternValuesChecked {
    const ASSUMPTIONS_MADE: &[Assumption] = &[];
    const ASSUMPTIONS_RELEASED: &[Assumption] = &[Assumption::ExternBaseTypesSpecified];

    fn run_pass(
        manifest: &mut Manifest,
        diagnostics: &mut Diagnostics,
    ) -> Result<HashSet<ObjectId>, DynError> {
        let mut removals = HashSet::new();

        for (extern_value_id, extern_value) in manifest.externs.iter_enumerated() {
            match extern_value.base_type.as_fixed_size() {
                Some(base_type) => {
                    if let Some(size_bits) = extern_value.size_bits
                        && size_bits.value > base_type.size_bits().into()
                    {
                        diagnostics.add(ExternInvalidSizeBits {
                            extern_name: extern_value.name.span,
                            size_bits: size_bits.span,
                            reason: "value is bigger than the base type size".into(),
                        });
                        removals.insert(extern_value_id.into());
                        continue;
                    }
                }
                None => {
                    diagnostics.add(ExternInvalidBaseType {
                        extern_name: extern_value.name.span,
                        base_type: (!extern_value.base_type.span.is_empty())
                            .then_some(extern_value.base_type.span),
                    });
                    removals.insert(extern_value_id.into());
                    continue;
                }
            }
        }

        Ok(removals)
    }
}