alduin 0.0.1

WIP: A toy compiler backend
Documentation
use std::fmt::Debug;

use super::op::Const;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum Type {
    Top = 0,
    Bool,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    Void,
}

impl Type {
    pub fn is_floating_point(self) -> bool {
        self == Type::F32 || self == Type::F64
    }

    pub fn is_integer(self) -> bool {
        self as u8 >= Type::I8 as u8 && (self as u8) <= Type::I64 as u8
    }

    /// Number of bytes required for the type's memory representation
    pub fn mem_size(self) -> usize {
        use Type::*;
        match self {
            Top | Void => unreachable!(),
            Bool => 1,
            I8 => 1,
            I16 => 2,
            I32 => 4,
            I64 => 8,
            F32 => 4,
            F64 => 8,
        }
    }
}

pub trait AnyTy: Clone + Copy + Debug + Sized {
    const TYPE: Type;
}

pub trait Ty: AnyTy {}

pub trait NumTy: Ty {
    fn constant(v: Self) -> Const;

    fn zero() -> Self;
}

pub trait IntTy: NumTy {}

#[derive(Debug, Clone, Copy, Hash)]
pub struct Top;

impl AnyTy for Top {
    const TYPE: Type = Type::Top;
}

impl AnyTy for () {
    const TYPE: Type = Type::Void;
}

impl AnyTy for bool {
    const TYPE: Type = Type::Bool;
}

impl Ty for () {}

impl Ty for bool {}

impl NumTy for bool {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::Bool(v)
    }

    #[inline]
    fn zero() -> Self {
        false
    }
}

impl IntTy for bool {}

impl AnyTy for i8 {
    const TYPE: Type = Type::I8;
}

impl Ty for i8 {}

impl NumTy for i8 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::I8(v)
    }

    #[inline]
    fn zero() -> Self {
        0
    }
}

impl IntTy for i8 {}

impl AnyTy for i16 {
    const TYPE: Type = Type::I16;
}

impl Ty for i16 {}

impl NumTy for i16 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::I16(v)
    }

    #[inline]
    fn zero() -> Self {
        0
    }
}

impl IntTy for i16 {}

impl AnyTy for i32 {
    const TYPE: Type = Type::I32;
}

impl Ty for i32 {}

impl NumTy for i32 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::I32(v)
    }

    #[inline]
    fn zero() -> Self {
        0
    }
}

impl IntTy for i32 {}

impl AnyTy for i64 {
    const TYPE: Type = Type::I64;
}

impl Ty for i64 {}

impl NumTy for i64 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::I64(v)
    }

    #[inline]
    fn zero() -> Self {
        0
    }
}

impl IntTy for i64 {}

pub trait FloatTy: NumTy {}

impl AnyTy for f32 {
    const TYPE: Type = Type::F32;
}

impl Ty for f32 {}

impl NumTy for f32 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::F32(v)
    }

    #[inline]
    fn zero() -> Self {
        0.
    }
}

impl FloatTy for f32 {}

impl AnyTy for f64 {
    const TYPE: Type = Type::F64;
}

impl Ty for f64 {}

impl NumTy for f64 {
    #[inline]
    fn constant(v: Self) -> Const {
        Const::F64(v)
    }

    #[inline]
    fn zero() -> Self {
        0.
    }
}

impl FloatTy for f64 {}