use std::{fmt, mem};
use crate::{
ast::{self, Ast},
boo::Boo,
func::{AvidFunc, Callable},
parser::{Operation, OpType},
promises::Promises,
typing::{Object, ObjectType},
Error, ErrorKind,
};
#[allow(unused_imports)]
use crate::builder::Builder;
#[allow(unused)]
pub struct Avid<'a, 'b> {
pub(crate) stack: Stack,
pub(crate) ops: Vec<Boo<'b, Operation>>,
pub(crate) current_op: usize,
pub(crate) provided: Vec<Option<Boo<'b, Callable<'b, 'a>>>>,
}
impl fmt::Debug for Avid<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Avid")
.field("stack", &self.stack)
.field("ops", &self.ops)
.field("current_op", &self.current_op)
.field(
"provided",
&self
.provided
.iter()
.map(|_| "<AvidFunc>")
.collect::<Vec<_>>(),
)
.finish()
}
}
impl PartialEq for Avid<'_, '_> {
fn eq(&self, other: &Self) -> bool {
self.stack == other.stack
&& self.ops == other.ops
&& self.current_op == other.current_op
&& self.provided.len() == other.provided.len()
}
}
impl<'a, 'b> Avid<'a, 'b> {
pub fn run(mut self, mut promised: Option<&mut Promises>) -> crate::Result<Stack> {
while !self.is_finished() {
self.advance(&mut promised)?;
}
Ok(self.stack)
}
pub fn new(src: &str) -> crate::Result<Avid> {
Builder::new(src).build()
}
pub fn from_ast(ast: Ast<'a>) -> Self {
let provided = ast
.provided
.into_iter()
.map(|x| x.map(|y| <ast::SendCallable<'_> as Into<Callable<'_, '_>>>::into(y).into()))
.collect();
Self {
stack: Stack::new(),
ops: ast.ops.into_iter().map(|x| x.into()).collect(),
current_op: 0,
provided,
}
}
pub fn from_ast_mut(ast: &'b mut Ast<'a>) -> Self {
let ops = ast.ops.iter_mut().map(|x| x.into()).collect();
let provided = ast
.provided
.iter_mut()
.map(|x| x.as_mut().map(|y| Callable::Borrowed(y).into()))
.collect();
Self {
stack: Stack::new(),
current_op: 0,
ops,
provided,
}
}
#[allow(clippy::type_complexity)]
pub fn run_mut(&mut self, mut promised: Option<&mut Promises>) -> crate::Result<Stack> {
while !self.is_finished() {
self.advance(&mut promised)?;
}
let mut s = Stack::new();
mem::swap(&mut s, &mut self.stack);
Ok(s)
}
fn is_finished(&self) -> bool {
self.ops.len() <= self.current_op
}
fn advance(&mut self, promised: &mut Option<&mut Promises>) -> crate::Result<()> {
let current_op = &*self.ops[self.current_op];
let increment: bool = match ¤t_op.typ {
OpType::WhileMarker => true,
OpType::DoMarker => panic!("Avid should never be given a do marker!"),
OpType::Bool(b) => {
self.stack.push(Object::Bool(*b));
true
}
OpType::If(offset) => {
let [cond] = self.stack.pop().map_err(|k| Error::new(k, current_op.loc.clone()))?;
if !cond.truthy() {
self.current_op += offset;
}
true
}
OpType::End(offset) => {
if let Some(offset) = offset {
self.current_op -= offset;
false
} else {
true
}
}
OpType::Int(i) => {
self.stack.push(Object::Num(*i));
true
}
OpType::String(s) => {
self.stack.push(Object::String(s.clone()));
true
}
OpType::Provided(p) => {
self.provided
.get_mut(*p)
.expect("Avid.provided should always have valid functions!")
.as_mut()
.expect("Avid.provided should always have valid functions!")
.call(&mut self.stack).map_err(|k| Error::new(k, current_op.loc.clone()))?;
true
}
OpType::Promise(p) => {
if let Some(promises) = promised {
if let Some(action) = promises.fns.get_mut(p) {
action.call(&mut self.stack).map_err(|k| Error::new(k, current_op.loc.clone()))?;
true
} else {
return Err(Error::new(ErrorKind::UnfulfilledPromise {
expected: p.clone(),
}, current_op.loc.clone()));
}
} else {
return Err(Error::new(ErrorKind::UnfulfilledPromise {
expected: p.clone(),
}, current_op.loc.clone()));
}
}
};
if increment {
self.current_op += 1;
}
Ok(())
}
}
#[derive(Debug, PartialEq, Default)]
pub struct Stack {
dat: Vec<Object>,
}
impl Stack {
pub fn new() -> Self {
Stack { dat: Vec::new() }
}
pub fn into_objects(self) -> Vec<Object> {
self.dat
}
pub fn push(&mut self, t: Object) {
self.dat.push(t)
}
pub fn pop<const NUM: usize>(&mut self) -> crate::Result<[Object; NUM], ErrorKind> {
let len = self.dat.len();
if len < NUM {
Err(ErrorKind::NotEnoughArgs {
expected: NUM,
got: len,
}) } else {
let res: [Object; NUM] = self
.dat
.drain((len - NUM)..len)
.collect::<Vec<_>>()
.try_into()
.expect("Should always have drained the right number of elements from stack!");
Ok(res)
}
}
pub fn pop_typed<const NUM: usize>(
&mut self,
expected_types: &'static [ObjectType; NUM],
) -> crate::Result<[Object; NUM], ErrorKind> {
if self.dat.len() < NUM {
return Err(ErrorKind::NotEnoughArgs {
expected: NUM,
got: self.dat.len(),
});
}
let typs = self
.dat
.iter()
.skip(self.dat.len() - NUM)
.map(Object::get_type)
.collect::<Vec<_>>();
for (expected_typ, actual_typ) in expected_types.iter().zip(typs.iter()) {
if expected_typ != actual_typ {
return Err(ErrorKind::IncorrectType {
expected: expected_types,
got: typs,
});
}
}
self.pop::<NUM>()
}
}