use std::{
fmt,
fmt::{Display, Formatter},
};
use crate::{
collections::symbol_map::Symbol,
eval::{
bc::{instr_arg::BcInstrArg, stack_ptr::BcStackPtr},
Arguments,
},
values::FrozenStringValue,
};
pub(crate) trait BcCallArgs: BcInstrArg {
fn pop_from_stack<'a, 'v>(&'a self, stack: &'a BcStackPtr<'v, '_>) -> Arguments<'v, 'a>;
}
#[derive(Debug)]
pub(crate) struct BcCallArgsFull {
pub(crate) pos_named: u32,
pub(crate) names: Box<[(Symbol, FrozenStringValue)]>,
pub(crate) args: bool,
pub(crate) kwargs: bool,
}
#[derive(Debug)]
pub(crate) struct BcCallArgsPos {
pub(crate) pos: u32,
}
impl BcCallArgsFull {
fn pos(&self) -> u32 {
assert!(self.pos_named as usize >= self.names.len());
self.pos_named - (self.names.len() as u32)
}
}
impl Display for BcCallArgsFull {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut first = true;
let mut write_sep = |f: &mut Formatter| {
if !first {
write!(f, " ")?;
}
first = false;
Ok(())
};
if self.pos() != 0 {
write_sep(f)?;
write!(f, "{}", self.pos())?;
}
for (_, name) in &*self.names {
write_sep(f)?;
write!(f, "{}", name.as_str())?;
}
if self.args {
write_sep(f)?;
write!(f, "*")?;
}
if self.kwargs {
write_sep(f)?;
write!(f, "**")?;
}
Ok(())
}
}
impl BcCallArgs for BcCallArgsFull {
fn pop_from_stack<'a, 'v>(&'a self, stack: &'a BcStackPtr<'v, '_>) -> Arguments<'v, 'a> {
stack.pop_args(self)
}
}
impl BcCallArgs for BcCallArgsPos {
fn pop_from_stack<'a, 'v>(&'a self, stack: &'a BcStackPtr<'v, '_>) -> Arguments<'v, 'a> {
stack.pop_args_pos(self)
}
}