use crate::{
exec::{Context, PasmResult},
inst::Op,
};
pub type ExecFunc = fn(&mut Context, &Op) -> PasmResult;
#[derive(Clone)]
pub struct ExecInst {
pub func: ExecFunc,
pub op: Op,
}
impl ExecInst {
pub fn new(inst: ExecFunc, op: Op) -> Self {
Self { func: inst, op }
}
}
#[macro_export]
macro_rules! inst {
($(#[$outer:meta])* $vis:vis $name:ident ($ctx:ident, $op:ident) { $( $code:tt )* }) => {
$(#[$outer])*
$vis fn $name($ctx: &mut $crate::exec::Context, $op: & $crate::inst::Op) -> $crate::exec::PasmResult {
use $crate::inst::Op::*;
$( $code )*
Ok(())
}
};
($(#[$outer:meta])* $vis:vis $name:ident ($ctx:ident) { $( $code:tt )* }) => {
$(#[$outer])*
$vis fn $name($ctx: &mut $crate::exec::Context, _: & $crate::inst::Op) -> $crate::exec::PasmResult {
$( $code )*
Ok(())
}
};
($(#[$outer:meta])* $vis:vis $name:ident { $( $code:tt )* }) => {
$(#[$outer])*
$vis fn $name(_: &mut $crate::exec::Context, _: & $crate::inst::Op) -> $crate::exec::PasmResult {
$( $code )*
Ok(())
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inst::Op::*;
#[test]
fn op_parsing() {
let ops = [
("200", Addr(200)),
("#x80", Literal(128)),
("#b001", Literal(1)),
("#800", Literal(800)),
(
"200,#8,be",
MultiOp(vec![Addr(200), Literal(8), Fail("be".into())]),
),
("", Null),
("ACC,r10,#x10", MultiOp(vec![Acc, Gpr(10), Literal(16)])),
];
for (op, res) in ops {
assert_eq!(Op::from(op), res);
}
}
}