<commit_before>//! Convert type parameters into local typedefs. This will break HierScope's `names` and `symbols`
//! indices.

use std::rc::Rc;

use elaborate::ty::Ty;
use elaborate::expr::Val;
use elaborate::hier::{self, HierItem, TypedefDecl};

pub fn type_param_elim(source: &mut hier::Source) {
    let mut elim = TypeParamEliminator {};
    elim.visit(source)
}

struct TypeParamEliminator {}

impl TypeParamEliminator {
    pub fn visit_item(&mut self, item: &mut HierItem) {
        match item {
            HierItem::Design(decl) => {
                for (_, inst) in decl.instances.borrow_mut().iter_mut() {
                    self.visit_instantiation(Rc::get_mut(inst).unwrap());
                }
            }
            HierItem::GenBlock(genblk) => {
                for item in &mut Rc::get_mut(genblk).unwrap().scope.items {
                    self.visit_item(item);
                }
            }
            HierItem::LoopGenBlock(loopgenblk) => {
                for (_, genblk) in loopgenblk.instances.borrow_mut().iter_mut() {
                    for item in &mut Rc::get_mut(genblk).unwrap().scope.items {
                        self.visit_item(item);
                    }
                }
            }
            _ => (),
        }
    }

    pub fn visit_instantiation(&mut self, inst: &mut hier::DesignInstantiation) {
        ::util::replace_with(&mut inst.scope.items, |items| {
            let mut params = Vec::new();
            let mut type_params = Vec::new();
            let mut ports = Vec::new();
            let mut others = Vec::new();

            for item in items {
                match item {
                    HierItem::Param(decl) => {
                        if let Ty::Type = decl.ty {
                            type_params.push(HierItem::Type(Rc::new(TypedefDecl {
                                ty: if let Val::Type(ref ty) = decl.init { ty.clone() } else { unreachable!() },
                                name: decl.name.clone()
                            })))
                        } else {
                            params.push(HierItem::Param(decl))
                        }
                    }
                    HierItem::DataPort(decl) => ports.push(HierItem::DataPort(decl)),
                    HierItem::InterfacePort(decl) => ports.push(HierItem::InterfacePort(decl)),
                    mut item => {
                        self.visit_item(&mut item);
                        others.push(item)
                    }
                }
            }

            params.extend(ports);
            params.extend(type_params);
            params.extend(others);
            params
        })
    }

    pub fn visit(&mut self, source: &mut hier::Source) {
        for unit in &mut source.units {<commit_msg>Move params into function<commit_after>//! Convert type parameters into local typedefs. This will break HierScope's `names` and `symbols`
//! indices.

use std::rc::Rc;

use elaborate::ty::Ty;
use elaborate::expr::Val;
use elaborate::hier::{self, HierItem, TypedefDecl};

pub fn type_param_elim(source: &mut hier::Source) {
    let mut elim = TypeParamEliminator {};
    elim.visit(source)
}

struct TypeParamEliminator {}

impl TypeParamEliminator {
    pub fn visit_item(&mut self, item: &mut HierItem) {
        match item {
            HierItem::Design(decl) => {
                for (_, inst) in decl.instances.borrow_mut().iter_mut() {
                    self.visit_instantiation(Rc::get_mut(inst).unwrap());
                }
            }
            HierItem::GenBlock(genblk) => {
                for item in &mut Rc::get_mut(genblk).unwrap().scope.items {
                    self.visit_item(item);
                }
            }
            HierItem::LoopGenBlock(loopgenblk) => {
                for (_, genblk) in loopgenblk.instances.borrow_mut().iter_mut() {
                    for item in &mut Rc::get_mut(genblk).unwrap().scope.items {
                        self.visit_item(item);
                    }
                }
            }
            _ => (),
        }
    }

    pub fn visit_instantiation(&mut self, inst: &mut hier::DesignInstantiation) {
        ::util::replace_with(&mut inst.scope.items, |items| {
            let mut ports = Vec::new();
            let mut others = Vec::new();

            for item in items {
                match item {
                    HierItem::Param(decl) => {
                        if let Ty::Type = decl.ty {
                            others.push(HierItem::Type(Rc::new(TypedefDecl {
                                ty: if let Val::Type(ref ty) = decl.init { ty.clone() } else { unreachable!() },
                                name: decl.name.clone()
                            })))
                        } else {
                            others.push(HierItem::Param(decl))
                        }
                    }
                    HierItem::DataPort(decl) => ports.push(HierItem::DataPort(decl)),
                    HierItem::InterfacePort(decl) => ports.push(HierItem::InterfacePort(decl)),
                    mut item => {
                        self.visit_item(&mut item);
                        others.push(item)
                    }
                }
            }

            ports.extend(others);
            ports
        })
    }

    pub fn visit(&mut self, source: &mut hier::Source) {
        for unit in &mut source.units {
{'fraction_non_alphanumeric': 0.12122328666175387, 'fraction_numerical': 0.0, 'mean_word_length': 1.4107460035523978, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6517014', 'n_tokens_mistral': 1502, 'n_tokens_neox': 1449, 'n_words': 289}