use alloc::{
collections::BTreeMap,
string::{String, ToString},
};
use core::fmt;
use spin::Mutex;
pub const DEFAULT_STACK_SIZE: usize = 256;
pub const PREDEFINED_REGISTERS: usize = 2;
lazy_static! {
pub(crate) static ref REGISTER_POINTER: Mutex<usize> = Mutex::new(PREDEFINED_REGISTERS);
pub(crate) static ref NAMED_REGISTERS: Mutex<BTreeMap<String, Register>> = Mutex::new(BTreeMap::new());
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Register {
StackPointer,
Accumulator,
Named {
name: String,
size: usize,
addr: usize,
},
}
impl Register {
pub fn named(name: impl fmt::Display) -> Option<Self> {
let registers = NAMED_REGISTERS.lock();
if let Some(r) = registers.get(&name.to_string()) {
Some(r.clone())
} else {
None
}
}
pub fn define(name: impl fmt::Display, size: usize) -> Self {
let mut rptr = REGISTER_POINTER.lock();
let mut registers = NAMED_REGISTERS.lock();
let result = Self::Named {
name: name.to_string(),
size,
addr: *rptr,
};
*rptr += size;
registers.insert(name.to_string(), result.clone());
result
}
pub fn get_addr(&self) -> usize {
match self {
Self::Named { addr, .. } => *addr,
Self::Accumulator => 0,
Self::StackPointer => 1
}
}
pub fn get_size(&self) -> usize {
match self {
Self::Named { size, .. } => *size,
_ => 1,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Literal {
Character(char),
Number(f64),
}
impl Literal {
pub fn ch(ch: char) -> Self {
Self::Character(ch)
}
pub fn num(n: f64) -> Self {
Self::Number(n)
}
pub fn get(&self) -> f64 {
match self {
Self::Character(ch) => *ch as i32 as f64,
Self::Number(n) => *n,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum Instruct {
Refer(Register),
DerefLoad,
DerefStore,
Load(Register),
Store(Register),
Push(Literal),
Pop,
Alloc(Register),
Free(Register),
Duplicate,
Add,
Subtract,
Multiply,
Divide,
OutputChar,
OutputNumber,
InputChar,
InputNumber,
Compare,
WhileNotZero,
EndWhile,
}