use crate::types::{self, Final, Type};
use std::cmp;
use std::sync::Arc;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct TypeName(pub &'static [u8]);
impl TypeName {
pub fn to_type<'brand>(&self, ctx: &types::Context<'brand>) -> Type<'brand> {
Type::complete(ctx, self.to_final())
}
pub fn to_final(&self) -> Arc<Final> {
let mut stack = Vec::with_capacity(16);
for c in self.0.iter().rev() {
match c {
b'1' => stack.push(Final::unit()),
b'2' => stack.push(Final::two_two_n(0)),
b'c' => stack.push(Final::two_two_n(3)),
b's' => stack.push(Final::two_two_n(4)),
b'i' => stack.push(Final::two_two_n(5)),
b'l' => stack.push(Final::two_two_n(6)),
b'h' => stack.push(Final::two_two_n(8)),
b'+' | b'*' => {
let left = stack.pop().expect("Illegal type name syntax!");
let right = stack.pop().expect("Illegal type name syntax!");
match c {
b'+' => stack.push(Final::sum(left, right)),
b'*' => stack.push(Final::product(left, right)),
_ => unreachable!(),
}
}
_ => panic!("Illegal type name syntax!"),
}
}
if stack.len() == 1 {
stack.pop().unwrap()
} else {
panic!("Illegal type name syntax!")
}
}
pub fn to_bit_width(&self) -> usize {
let mut stack = Vec::with_capacity(16);
for c in self.0.iter().rev() {
match c {
b'1' => stack.push(0),
b'2' => stack.push(1),
b'c' => stack.push(8),
b's' => stack.push(16),
b'i' => stack.push(32),
b'l' => stack.push(64),
b'h' => stack.push(256),
b'+' | b'*' => {
let left = stack.pop().expect("Illegal type name syntax!");
let right = stack.pop().expect("Illegal type name syntax!");
match c {
b'+' => stack.push(1 + cmp::max(left, right)),
b'*' => stack.push(left + right),
_ => unreachable!(),
}
}
_ => panic!("Illegal type name syntax!"),
}
}
if stack.len() == 1 {
stack.pop().unwrap()
} else {
panic!("Illegal type name syntax!")
}
}
}