origen_metal 1.4.0

Bare metal APIs for the Origen SDK
use crate::prog_gen::FlowID;
use crate::prog_gen::PGM;
use crate::Result;
use crate::ast::{Node, Processor, Return};
use std::collections::HashMap;

pub struct DuplicateIDs {
    ids: HashMap<FlowID, Node<PGM>>,
}

pub fn run(node: &Node<PGM>) -> Result<()> {
    let mut p = DuplicateIDs {
        ids: HashMap::new(),
    };
    let _ = node.process(&mut p)?;
    Ok(())
}

impl DuplicateIDs {
    fn validate_id(&mut self, id: &FlowID, node: &Node<PGM>) -> Result<()> {
        if self.ids.contains_key(id) {
            if crate::PROG_GEN_CONFIG.debug_enabled() {
                bail!(
                    "The ID '{}' was assigned more than once, by the following flow lines:\n{}\n{}",
                    id,
                    self.ids[id].meta_string(),
                    node.meta_string()
                );
            } else {
                bail!(
                    "The ID '{}' was assigned more than once, run again with the --debug \
                 switch enabled to trace back to a flow line",
                    id
                );
            }
        } else {
            self.ids
                .insert(id.to_owned(), node.replace_children(vec![]));
        }
        Ok(())
    }
}

impl Processor<PGM> for DuplicateIDs {
    fn on_node(&mut self, node: &Node<PGM>) -> crate::Result<Return<PGM>> {
        Ok(match &node.attrs {
            PGM::Test(_, id) | PGM::TestStr(_, id, _, _, _) | PGM::Cz(_, _, id) => {
                self.validate_id(id, node)?;
                Return::ProcessChildren
            }
            PGM::Group(_, _, _, id) => {
                if let Some(id) = id {
                    self.validate_id(id, node)?;
                }
                Return::ProcessChildren
            }
            _ => Return::ProcessChildren,
        })
    }
}