device-driver-mir 2.0.0

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

use crate::{
    model::{LendingIterator, Manifest, UniqueId},
    passes::{Assumption, Pass},
};
use device_driver_common::specifiers::BaseType;
use device_driver_diagnostics::{Diagnostics, DynError, errors::BoolFieldTooLarge};

/// Check all bool fields. They must be exactly zero or one bits
pub struct BoolFieldsChecked;

impl Pass for BoolFieldsChecked {
    const ASSUMPTIONS_MADE: &[Assumption] = &[Assumption::FieldBaseTypesSpecified];
    const ASSUMPTIONS_RELEASED: &[Assumption] = &[];

    fn run_pass(
        manifest: &mut Manifest,
        diagnostics: &mut Diagnostics,
    ) -> Result<HashSet<UniqueId>, DynError> {
        let mut iter = manifest.iter_objects_with_config_mut();
        while let Some((object, _)) = iter.next() {
            let Some(field_set) = object.as_field_set_mut() else {
                continue;
            };

            for field in field_set.fields.iter_mut() {
                if field.base_type == BaseType::Bool && field.field_address.len() != 1 {
                    diagnostics.add(BoolFieldTooLarge {
                        base_type: if field.base_type.span.is_empty() {
                            None
                        } else {
                            Some(field.base_type.span)
                        },
                        address: field.field_address.span,
                        address_bits: field.field_address.len() as u32,
                        address_start: field.field_address.start,

                        field_set_context: field_set.name.span,
                    });
                    // To fix for further use, set the len to just 1
                    field.field_address.end = field.field_address.start;
                }
            }
        }

        Ok(Default::default())
    }
}