pub use self::TypeKind::*;
use crate::util::write_implode;
use std;
use std::sync::Arc;
pub type Type = Arc<TypeKind>;
#[derive(Debug, PartialEq, Eq)]
pub enum TypeKind {
VoidType,
TimeType,
IntType(usize),
EnumType(usize),
PointerType(Type),
SignalType(Type),
ArrayType(usize, Type),
StructType(Vec<Type>),
FuncType(Vec<Type>, Type),
EntityType(Vec<Type>, Vec<Type>),
}
impl std::fmt::Display for TypeKind {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
VoidType => write!(f, "void"),
TimeType => write!(f, "time"),
IntType(l) => write!(f, "i{}", l),
EnumType(l) => write!(f, "n{}", l),
PointerType(ref ty) => write!(f, "{}*", ty),
SignalType(ref ty) => write!(f, "{}$", ty),
ArrayType(l, ref ty) => write!(f, "[{} x {}]", l, ty),
StructType(ref tys) => {
write!(f, "{{")?;
write_implode(f, ", ", tys.iter())?;
write!(f, "}}")?;
Ok(())
}
FuncType(ref args, ref ret) => {
write!(f, "(")?;
write_implode(f, ", ", args.iter())?;
write!(f, ") {}", ret)?;
Ok(())
}
EntityType(ref ins, ref outs) => {
write!(f, "(")?;
write_implode(f, ", ", ins.iter())?;
write!(f, ";")?;
write_implode(f, ", ", outs.iter())?;
write!(f, ")")?;
Ok(())
}
}
}
}
impl TypeKind {
pub fn unwrap_int(&self) -> usize {
match *self {
IntType(size) => size,
_ => panic!("unwrap_int called on {}", self),
}
}
pub fn unwrap_enum(&self) -> usize {
match *self {
EnumType(size) => size,
_ => panic!("unwrap_enum called on {}", self),
}
}
pub fn unwrap_pointer(&self) -> &Type {
match *self {
PointerType(ref ty) => ty,
_ => panic!("unwrap_pointer called on {}", self),
}
}
pub fn unwrap_signal(&self) -> &Type {
match *self {
SignalType(ref ty) => ty,
_ => panic!("unwrap_signal called on {}", self),
}
}
pub fn unwrap_array(&self) -> (usize, &Type) {
match *self {
ArrayType(len, ref ty) => (len, ty),
_ => panic!("unwrap_array called on {}", self),
}
}
pub fn unwrap_struct(&self) -> &[Type] {
match *self {
StructType(ref fields) => fields,
_ => panic!("unwrap_struct called on {}", self),
}
}
pub fn unwrap_func(&self) -> (&[Type], &Type) {
match *self {
FuncType(ref args, ref ret) => (args, ret),
_ => panic!("unwrap_func called on {}", self),
}
}
pub fn unwrap_entity(&self) -> (&[Type], &[Type]) {
match *self {
EntityType(ref ins, ref outs) => (ins, outs),
_ => panic!("unwrap_entity called on {}", self),
}
}
pub fn is_void(&self) -> bool {
match *self {
VoidType => true,
_ => false,
}
}
pub fn is_time(&self) -> bool {
match *self {
TimeType => true,
_ => false,
}
}
pub fn is_int(&self) -> bool {
match *self {
IntType(..) => true,
_ => false,
}
}
pub fn is_enum(&self) -> bool {
match *self {
EnumType(..) => true,
_ => false,
}
}
pub fn is_pointer(&self) -> bool {
match *self {
PointerType(..) => true,
_ => false,
}
}
pub fn is_signal(&self) -> bool {
match *self {
SignalType(..) => true,
_ => false,
}
}
pub fn is_array(&self) -> bool {
match *self {
ArrayType(..) => true,
_ => false,
}
}
pub fn is_struct(&self) -> bool {
match *self {
StructType(..) => true,
_ => false,
}
}
pub fn is_func(&self) -> bool {
match *self {
FuncType(..) => true,
_ => false,
}
}
pub fn is_entity(&self) -> bool {
match *self {
EntityType(..) => true,
_ => false,
}
}
}
pub fn void_ty() -> Type {
Type::new(VoidType)
}
pub fn time_ty() -> Type {
Type::new(TimeType)
}
pub fn int_ty(size: usize) -> Type {
Type::new(IntType(size))
}
pub fn enum_ty(size: usize) -> Type {
Type::new(EnumType(size))
}
pub fn pointer_ty(ty: Type) -> Type {
Type::new(PointerType(ty))
}
pub fn signal_ty(ty: Type) -> Type {
Type::new(SignalType(ty))
}
pub fn array_ty(size: usize, ty: Type) -> Type {
Type::new(ArrayType(size, ty))
}
pub fn struct_ty(fields: Vec<Type>) -> Type {
Type::new(StructType(fields))
}
pub fn func_ty(args: Vec<Type>, ret: Type) -> Type {
Type::new(FuncType(args, ret))
}
pub fn entity_ty(ins: Vec<Type>, outs: Vec<Type>) -> Type {
Type::new(EntityType(ins, outs))
}