use super::{AnyConst32, Register};
use crate::{core::UntypedVal, engine::translator::TranslationError, Error};
use std::vec::{Drain, Vec};
#[cfg(doc)]
use super::Instruction;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ProviderSliceRef(AnyConst32);
impl ProviderSliceRef {
fn from_index(index: usize) -> Result<Self, Error> {
u32::try_from(index)
.map_err(|_| Error::from(TranslationError::ProviderSliceOverflow))
.map(AnyConst32::from)
.map(Self)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Provider<T> {
Register(Register),
Const(T),
}
impl<T> Provider<T> {
pub fn into_register(self) -> Option<Register> {
match self {
Self::Register(register) => Some(register),
Self::Const(_) => None,
}
}
}
pub type UntypedProvider = Provider<UntypedVal>;
impl From<Register> for UntypedProvider {
fn from(register: Register) -> Self {
Self::Register(register)
}
}
impl From<UntypedVal> for UntypedProvider {
fn from(register: UntypedVal) -> Self {
Self::Const(register)
}
}
impl UntypedProvider {
pub fn immediate(value: impl Into<UntypedVal>) -> Self {
Self::from(value.into())
}
}
#[derive(Debug)]
pub struct ProviderSliceStack<T> {
ends: Vec<usize>,
providers: Vec<Provider<T>>,
}
impl<T> Default for ProviderSliceStack<T> {
fn default() -> Self {
Self {
ends: Vec::new(),
providers: Vec::new(),
}
}
}
impl<T> ProviderSliceStack<T> {
pub fn reset(&mut self) {
self.ends.clear();
self.providers.clear();
}
pub fn push<I>(&mut self, providers: I) -> Result<ProviderSliceRef, Error>
where
I: IntoIterator<Item = Provider<T>>,
{
self.providers.extend(providers);
let end = self.providers.len();
let index = self.ends.len();
self.ends.push(end);
ProviderSliceRef::from_index(index)
}
pub fn pop(&mut self) -> Option<Drain<Provider<T>>> {
let end = self.ends.pop()?;
let start = self.ends.last().copied().unwrap_or(0);
Some(self.providers.drain(start..end))
}
}