|
|
|
use std::fmt::Debug;
|
|
|
|
|
|
|
|
use crate::asm::instr::Cond;
|
|
|
|
use crate::builtin::defs::BuiltinOp;
|
|
|
|
use crate::module::{EvalRes, OpTrait};
|
|
|
|
use crate::runtime::fault::Fault;
|
|
|
|
use crate::runtime::run_thread::{info::ThreadInfo, state::RunState};
|
|
|
|
use sexp::{Sexp, Atom};
|
|
|
|
|
|
|
|
/// A higher level simple opration
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum OpKind {
|
|
|
|
BuiltIn(BuiltinOp),
|
|
|
|
/// Instruction added by an extension
|
|
|
|
Ext(Box<dyn OpTrait>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Op {
|
|
|
|
pub cond: Option<Cond>,
|
|
|
|
pub kind: OpKind,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl OpTrait for Op {
|
|
|
|
fn execute(&self, ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
|
|
|
|
if let Some(cond) = self.cond {
|
|
|
|
if !state.test_cond(cond) {
|
|
|
|
return Ok(EvalRes {
|
|
|
|
cycles: 0,
|
|
|
|
advance: 1,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match &self.kind {
|
|
|
|
OpKind::BuiltIn(op) => {
|
|
|
|
op.execute(ti, state)
|
|
|
|
}
|
|
|
|
OpKind::Ext(op) => {
|
|
|
|
op.execute(ti, state)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_sexp(&self) -> Sexp {
|
|
|
|
let mut se = match &self.kind {
|
|
|
|
OpKind::BuiltIn(op) => op.to_sexp(),
|
|
|
|
OpKind::Ext(op) => op.to_sexp()
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(cond) = self.cond {
|
|
|
|
if let Sexp::List(items) = &mut se {
|
|
|
|
if let Some(Sexp::Atom(Atom::S(s))) = &mut items.get_mut(0) {
|
|
|
|
s.push('.');
|
|
|
|
s.push_str(&cond.to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
se
|
|
|
|
}
|
|
|
|
}
|