use crate::instr::{HLOp, Op}; use sexp::Sexp; use crate::error::Error; use crate::data::literal::{RoutineName, Label}; use crate::parse::sexp_expect::expect_string_atom; use crate::parse::parse_data::{parse_rd, parse_wr, parse_label}; use crate::parse::parse_cond::parse_cond; pub fn parse_op(keyword: &str, far : bool, mut arg_tokens: impl Iterator) -> Result { Ok(match keyword { "j" => { let dest = parse_label(arg_tokens.next())?; if far { HLOp::L(Op::FarJump(dest)) } else { HLOp::Jump(dest) } } "call" => { let dest = RoutineName(expect_string_atom(arg_tokens.next())?); let mut args = vec![]; for t in arg_tokens { args.push(parse_rd(Some(t))?); } HLOp::L(Op::Call(dest, args)) } "ret" => { let mut args = vec![]; for t in arg_tokens { args.push(parse_rd(Some(t))?); } HLOp::L(Op::Ret(args)) } "routine" => { let dest = RoutineName(expect_string_atom(arg_tokens.next())?); HLOp::L(Op::Routine(dest)) } "s" => { HLOp::L(Op::Skip(parse_rd(arg_tokens.next())?)) } "sif" => { let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; let offs = parse_rd(arg_tokens.next())?; HLOp::L(Op::SkipIf(cond, offs)) } "jif" => { let cond = parse_cond(&expect_string_atom(arg_tokens.next())?)?; let dest = parse_label(arg_tokens.next())?; HLOp::JumpIf(cond, dest) } "barrier" => { HLOp::L(Op::Barrier(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), })) } "fault" => { HLOp::L(Op::Fault(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), })) } "ld" => { HLOp::L(Op::Mov( parse_wr(arg_tokens.next())?, parse_rd(arg_tokens.next())? )) } "cmp" => { HLOp::L(Op::Cmp( parse_rd(arg_tokens.next())?, parse_rd(arg_tokens.next())? )) } "tst" => { let arg = parse_rd(arg_tokens.next())?; HLOp::L(Op::Cmp(arg, arg)) } "inc" => { HLOp::L(Op::Inc( parse_wr(arg_tokens.next())? )) } "dec" => { HLOp::L(Op::Dec( parse_wr(arg_tokens.next())? )) } // TODO more instructions other => { if let Some(label) = other.strip_prefix(':') { let label = Label::Named(label.to_string()); if far { HLOp::L(Op::FarLabel(label)) } else { HLOp::Label(label) } } else { return Err(Error::Parse(format!("Unknown instruction: {}", other).into())); } } }) }