use crate::abend::Abend;
use crate::storage::{Loc, Val};
use crate::store::{self, ProgramFacts};
use crate::vocab::Pos;
use numeric::precision::{Fixed, Places};
type R<T> = Result<T, Abend>;
pub trait Host<P: Copy> {
type Facts: ProgramFacts;
fn facts(&self) -> Self::Facts;
fn mem(&mut self) -> &mut [u8];
fn locate(&mut self, place: P, receiving: bool) -> R<Loc>;
fn integer(&mut self, place: P, pos: Pos) -> R<i64>;
fn assign(&mut self, dest: Loc, val: Val, src: Option<Loc>, pos: Pos) -> R<()>;
fn store_fixed(&mut self, dest: Loc, value: &Fixed, pos: Pos) -> R<()>;
}
pub trait Values<P: Copy, O>: Host<P> {
fn value(&mut self, operand: &O, pos: Pos) -> R<Val>;
}
pub fn read<P: Copy>(x: &mut impl Host<P>, loc: Loc, pos: Pos) -> R<Val> {
store::read(&x.facts(), x.mem(), loc, pos)
}
pub fn set_integer<P: Copy>(x: &mut impl Host<P>, place: P, value: i64, pos: Pos) -> R<()> {
let dest = x.locate(place, false)?;
x.store_fixed(dest, &Fixed::new(value as i128, Places::new(19, 0)), pos)
}