use std::fmt::{Display, Formatter}; use std::rc::Rc; pub type Register = usize; pub type StackFrameOffset = isize; pub type ConstantName = Rc; pub type FunctionName = Rc; pub type ArgCount = usize; pub type CallerPopCount = usize; pub enum Instruction { Move(MoveOperand, Location), Push(PushOperand), InvokeStatic(FunctionName, ArgCount), InvokePlatformStatic(FunctionName, ArgCount), Add(AddOperand, AddOperand, Location), Subtract(SubtractOperand, SubtractOperand, Location), Pop(Option), SetReturnValue(ReturnOperand), Return, } impl Display for Instruction { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Instruction::Move(source, destination) => { write!(f, "mov {}, {}", source, destination) } Instruction::Push(source) => write!(f, "push {}", source), Instruction::InvokeStatic(name, arg_count) => { write!(f, "invoke_static {} (arg_count: {})", name, arg_count) } Instruction::InvokePlatformStatic(name, arg_count) => { write!( f, "invoke_platform_static {} (arg_count: {})", name, arg_count ) } Instruction::Pop(maybe_destination) => { if let Some(destination) = maybe_destination { write!(f, "pop {}", destination) } else { write!(f, "pop") } } Instruction::Add(left, right, destination) => { write!(f, "add {}, {}, {}", left, right, destination) } Instruction::Subtract(left, right, destination) => { write!(f, "sub {}, {}, {}", left, right, destination) } Instruction::SetReturnValue(source) => { write!(f, "srv {}", source) } Instruction::Return => { write!(f, "ret") } } } } pub enum Location { Register(Register), StackFrameOffset(StackFrameOffset), } impl Display for Location { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Location::Register(register) => { write!(f, "r{}", register) } Location::StackFrameOffset(offset) => { if offset.is_positive() || *offset == 0 { write!(f, "fp+{}", offset) } else { write!(f, "fp{}", offset) } } } } } pub enum MoveOperand { Location(Location), Int(i32), String(Rc), } impl Display for MoveOperand { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { MoveOperand::Location(location) => { write!(f, "{}", location) } MoveOperand::Int(i) => { write!(f, "{}", i) } MoveOperand::String(s) => { write!(f, "{}", s) } } } } pub enum PushOperand { Location(Location), Int(i32), String(Rc), } impl Display for PushOperand { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { PushOperand::Location(location) => { write!(f, "{}", location) } PushOperand::Int(i) => { write!(f, "{}", i) } PushOperand::String(s) => { write!(f, "{}", s) } } } } pub enum AddOperand { Location(Location), Int(i32), String(Rc), } impl Display for AddOperand { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { AddOperand::Location(location) => { write!(f, "{}", location) } AddOperand::Int(i) => { write!(f, "{}", i) } AddOperand::String(s) => { write!(f, "{}", s) } } } } pub enum SubtractOperand { Location(Location), Int(i32), } impl Display for SubtractOperand { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { SubtractOperand::Location(location) => { write!(f, "{}", location) } SubtractOperand::Int(i) => { write!(f, "{}", i) } } } } pub enum ReturnOperand { Location(Location), Int(i32), String(Rc), } impl Display for ReturnOperand { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { ReturnOperand::Location(location) => { write!(f, "{}", location) } ReturnOperand::Int(i) => { write!(f, "{}", i) } ReturnOperand::String(s) => { write!(f, "{}", s) } } } }