robson_compiler 0.1.6

Dependency of the robson cli
Documentation
use std::{
  error::Error,
  fmt::Display,
  num::{ParseFloatError, ParseIntError},
  ops::{Deref, DerefMut},
};

#[derive(Debug)]
pub struct InstructionParam {
  pub convert: bool,
  pub kind: usize,
  pub byte: TypedByte,
}

impl InstructionParam {
  pub fn fn_is_empty(&self) -> bool {
    (*self.byte).is_empty() && self.kind == 0 && self.convert
  }
}
impl Display for InstructionParam {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    write!(
      f,
      "{} {} {}",
      match self.kind {
        0 => "comeu",
        1 => "chupou",
        2 => "fudeu",
        3 => "penetrou",
        _ => "unknwon",
      },
      self.byte,
      if self.convert { "robson" } else { "" }
    )
  }
}
#[derive(Debug)]
pub struct Instruction {
  pub opcode: u8,
  pub params: [InstructionParam; 3],
}
impl Display for Instruction {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    let mut params = String::new();

    for (index, i) in self.params.iter().enumerate() {
      if !i.fn_is_empty() {
        params.push_str(&format!("param{} {}\n", index + 1, i));
      }
    }

    write!(f, "opcode: {}\n{params}", self.opcode)
  }
}
#[derive(Debug)]
pub struct IError {
  pub error: String,
}
impl IError {
  pub fn message<T>(error: T) -> Self
  where
    T: ToString,
  {
    Self {
      error: error.to_string(),
    }
  }
}
impl From<ParseIntError> for IError {
  fn from(err: ParseIntError) -> Self {
    Self {
      error: err.to_string(),
    }
  }
}
impl From<ParseFloatError> for IError {
  fn from(err: ParseFloatError) -> Self {
    Self {
      error: err.to_string(),
    }
  }
}
impl From<std::io::Error> for IError {
  fn from(err: std::io::Error) -> Self {
    Self {
      error: err.to_string(),
    }
  }
}
impl Display for IError {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    write!(f, "{}", self.error)
  }
}
impl Error for IError {}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct TypedByte {
  pub value: [u8; 4],
  pub r#type: Type,
}
impl From<u32> for TypedByte {
  fn from(value: u32) -> Self {
    Self {
      value: value.to_be_bytes(),
      r#type: Type::Usigned,
    }
  }
}
impl From<i32> for TypedByte {
  fn from(value: i32) -> Self {
    Self {
      value: value.to_be_bytes(),
      r#type: Type::Signed,
    }
  }
}
impl From<f32> for TypedByte {
  fn from(value: f32) -> Self {
    Self {
      value: value.to_be_bytes(),
      r#type: Type::Floating,
    }
  }
}

impl From<[u8; 4]> for TypedByte {
  fn from(value: [u8; 4]) -> Self {
    Self {
      value,
      r#type: Type::Usigned,
    }
  }
}

impl From<bool> for TypedByte {
  fn from(value: bool) -> Self {
    TypedByte {
      value: (value as u32).to_be_bytes(),
      r#type: Type::Usigned,
    }
  }
}

impl Deref for TypedByte {
  type Target = [u8; 4];
  fn deref(&self) -> &Self::Target {
    &self.value
  }
}
impl Display for TypedByte {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    write!(
      f,
      "{}",
      match self.r#type {
        Type::Usigned =>
          format!("{}", u32::from_be_bytes(self.value)),
        Type::Signed =>
          format!("i{}", i32::from_be_bytes(self.value)),
        Type::Floating =>
          format!("f{}", f32::from_be_bytes(self.value)),
      }
    )
  }
}

impl TypedByte {
  pub fn force_u32(&self) -> Option<u32> {
    if self.r#type != Type::Usigned {
      None
    } else {
      Some(u32::from_be_bytes(self.value))
    }
  }
  pub fn convert(&mut self, to_convert: Type) {
    self.r#type = to_convert;

    match to_convert {
      Type::Usigned => match self.r#type {
        Type::Usigned => {}
        Type::Signed => {
          self.value =
            (i32::from_be_bytes(self.value) as u32).to_be_bytes()
        }
        Type::Floating => {
          self.value =
            (f32::from_be_bytes(self.value) as u32).to_be_bytes()
        }
      },
      Type::Signed => match self.r#type {
        Type::Usigned => {
          self.value =
            (u32::from_be_bytes(self.value) as i32).to_be_bytes()
        }
        Type::Signed => {}
        Type::Floating => {
          self.value =
            (f32::from_be_bytes(self.value) as i32).to_be_bytes()
        }
      },
      Type::Floating => match self.r#type {
        Type::Usigned => {
          self.value =
            (u32::from_be_bytes(self.value) as f32).to_be_bytes()
        }
        Type::Signed => {
          self.value =
            (i32::from_be_bytes(self.value) as f32).to_be_bytes()
        }
        Type::Floating => {}
      },
    }
  }
}

#[derive(Default, Debug)]
pub struct Stack<T> {
  pub vec: Vec<T>,
}
impl<T: std::fmt::Debug> Display for Stack<T> {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    let mut string = String::new();
    for i in &self.vec {
      string.push_str(&format!("{i:?}, "));
    }
    write!(f, "[{}]", string)
  }
}
impl<T> Deref for Stack<T> {
  type Target = Vec<T>;
  fn deref(&self) -> &Self::Target {
    &self.vec
  }
}
impl<T> DerefMut for Stack<T> {
  fn deref_mut(&mut self) -> &mut Self::Target {
    &mut self.vec
  }
}
impl<T: Copy> Stack<T> {
  pub fn top(&self) -> Option<T> {
    if !self.vec.is_empty() {
      return Some(self.vec[self.len() - 1]);
    }
    None
  }
}

const TYPES: [Type; 3] =
  [Type::Usigned, Type::Signed, Type::Floating];

#[derive(Clone, Copy, PartialEq, Debug, Eq, PartialOrd)]
pub enum Type {
  Usigned = 0,
  Signed = 1,
  Floating = 2,
}

impl From<usize> for Type {
  fn from(value: usize) -> Self {
    TYPES[value]
  }
}
impl Default for Type {
  fn default() -> Self {
    Self::Usigned
  }
}