vast 0.3.3

Verilog AST library
Documentation
use crate::subset::ast::*;
use std::rc::Rc;

impl InstancePath {
    pub fn new(path: &str) -> InstancePath {
        let p: Vec<String> = path.split('.').map(|x| x.to_string()).collect();
        InstancePath { path: p }
    }

    pub fn path(&self) -> &Vec<Id> {
        &self.path
    }

    pub fn add_inst(&mut self, name: &str) {
        self.path.push(name.to_string());
    }
}

impl ExprConcat {
    pub fn exprs(&self) -> &Vec<Expr> {
        &self.exprs
    }

    pub fn add_expr<E>(&mut self, expr: E)
    where
        E: Into<Expr>,
    {
        self.exprs.push(expr.into());
    }
}

impl Expr {
    pub fn id(&self) -> String {
        match self {
            Expr::Ref(id) => id.to_string(),
            Expr::Signed(e) => e.id(),
            _ => panic!("Error: do not support id"),
        }
    }

    pub fn new_ref<S>(name: S) -> Expr
    where
        S: AsRef<str>,
    {
        Expr::Ref(name.as_ref().to_string())
    }

    pub fn new_signed_ref<S>(name: S) -> Expr
    where
        S: AsRef<str>,
    {
        Expr::Signed(Rc::new(Expr::Ref(name.as_ref().to_string())))
    }

    pub fn new_signed<E>(expr: E) -> Expr
    where
        E: Into<Expr>,
    {
        Expr::Signed(Rc::new(expr.into()))
    }

    pub fn new_str(value: &str) -> Expr {
        Expr::Str(value.to_string())
    }

    pub fn new_ulit_dec(width: u32, value: &str) -> Expr {
        assert!(width > 0, "Error: width must be greater than zero");
        Expr::ULit(width, Radix::Dec, value.to_string())
    }

    pub fn new_ulit_hex(width: u32, value: &str) -> Expr {
        assert!(width > 0, "Error: width must be greater than zero");
        Expr::ULit(width, Radix::Hex, value.to_string())
    }

    pub fn new_ulit_bin(width: u32, value: &str) -> Expr {
        assert!(width > 0, "Error: width must be greater than zero");
        Expr::ULit(width, Radix::Bin, value.to_string())
    }

    pub fn new_bit_or<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::BitOr, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_bit_and<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::BitAnd, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_logical_or<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::LogOr, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_logical_and<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::LogAnd, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_add<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Add, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_shift_left<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::ShiftLeft, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_sub<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Sub, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_gt<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Gt, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_lt<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Lt, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_geq<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Geq, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_leq<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Leq, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_eq<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Equal, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_neq<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::NotEqual, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_mul<L, R>(lhs: L, rhs: R) -> Expr
    where
        L: Into<Expr>,
        R: Into<Expr>,
    {
        Expr::Binop(Binop::Mul, Rc::new(lhs.into()), Rc::new(rhs.into()))
    }

    pub fn new_mux<C, T, F>(cond: C, tru: T, fal: F) -> Expr
    where
        C: Into<Expr>,
        T: Into<Expr>,
        F: Into<Expr>,
    {
        Expr::Terop(
            Terop::Mux,
            Rc::new(cond.into()),
            Rc::new(tru.into()),
            Rc::new(fal.into()),
        )
    }

    pub fn new_not<E>(exp: E) -> Expr
    where
        E: Into<Expr>,
    {
        Expr::Unop(Unop::Not, Rc::new(exp.into()))
    }

    pub fn new_slice<H, L>(var: &str, hi: H, lo: L) -> Expr
    where
        H: Into<Expr>,
        L: Into<Expr>,
    {
        Expr::Terop(
            Terop::Slice,
            Rc::new(Expr::new_ref(var)),
            Rc::new(hi.into()),
            Rc::new(lo.into()),
        )
    }

    pub fn new_index_slice<E>(var: &str, lo: E, width: u32) -> Expr
    where
        E: Into<Expr>,
    {
        Expr::Terop(
            Terop::IndexSlice,
            Rc::new(Expr::new_ref(var)),
            Rc::new(lo.into()),
            Rc::new(Expr::new_int(width as i32)),
        )
    }

    pub fn new_index_bit(var: &str, bit: i32) -> Expr {
        Expr::Binop(
            Binop::IndexBit,
            Rc::new(Expr::new_ref(var)),
            Rc::new(Expr::new_int(bit)),
        )
    }

    pub fn new_index_expr<E>(var: &str, expr: E) -> Expr
    where
        E: Into<Expr>,
    {
        Expr::Binop(
            Binop::IndexBit,
            Rc::new(Expr::new_ref(var)),
            Rc::new(expr.into()),
        )
    }

    pub fn new_int(value: i32) -> Expr {
        Expr::Int(value)
    }

    pub fn new_ipath(path: &str) -> Expr {
        Expr::IPath(InstancePath::new(path), None)
    }

    pub fn new_ipath_with_index(path: &str, index: &str) -> Expr {
        Expr::IPath(InstancePath::new(path), Some(Rc::new(Expr::new_ref(index))))
    }

    pub fn new_call(name: &str, params: Vec<Expr>) -> Expr {
        Expr::Call(name.to_string(), params)
    }

    pub fn new_repeat<E>(times: u64, expr: E) -> Expr
    where
        E: Into<Expr>,
    {
        Expr::Repeat(times, Rc::new(expr.into()))
    }
}

impl AttributeTy {
    pub fn new_val(value: &str) -> AttributeTy {
        AttributeTy::Val(value.to_string())
    }

    pub fn new_stmt(id: &str, value: &str) -> AttributeTy {
        AttributeTy::Stmt(id.to_string(), value.to_string())
    }
}

impl Attribute {
    pub fn attrs(&self) -> &Vec<AttributeTy> {
        &self.attrs
    }

    pub fn add_val(&mut self, value: &str) {
        self.attrs.push(AttributeTy::new_val(value));
    }

    pub fn add_stmt(&mut self, id: &str, value: &str) {
        self.attrs.push(AttributeTy::new_stmt(id, value));
    }

    pub fn add_attr(&mut self, attr: AttributeTy) {
        self.attrs.push(attr);
    }
}

impl Instance {
    pub fn new(id: &str, prim: &str) -> Instance {
        Instance {
            id: id.to_string(),
            prim: prim.to_string(),
            params: Map::new(),
            ports: Map::new(),
            attr: Attribute::default(),
        }
    }

    pub fn id(&self) -> String {
        self.id.to_string()
    }

    pub fn prim(&self) -> String {
        self.prim.to_string()
    }

    pub fn attr(&self) -> &Attribute {
        &self.attr
    }

    pub fn param_map(&self) -> &Map {
        &self.params
    }

    pub fn port_map(&self) -> &Map {
        &self.ports
    }

    pub fn set_id(&mut self, id: &str) {
        self.id = id.to_string();
    }

    pub fn set_prim(&mut self, prim: &str) {
        self.prim = prim.to_string();
    }

    pub fn set_attr(&mut self, attr: Attribute) {
        self.attr = attr;
    }

    pub fn add_param<E>(&mut self, param: &str, value: E)
    where
        E: Into<Expr>,
    {
        self.params.insert(param.to_string(), value.into());
    }

    pub fn add_param_uint(&mut self, param: &str, value: u32) {
        self.params.insert(
            param.to_string(),
            Expr::new_ulit_dec(32, &value.to_string()),
        );
    }

    pub fn add_param_str(&mut self, param: &str, value: &str) {
        self.params.insert(param.to_string(), Expr::new_str(value));
    }

    pub fn connect<E>(&mut self, port: &str, expr: E)
    where
        E: Into<Expr>,
    {
        self.ports.insert(port.to_string(), expr.into());
    }

    pub fn connect_ref(&mut self, port: &str, id: &str) {
        self.ports.insert(port.to_string(), Expr::new_ref(id));
    }
}