use crate::instr::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 { "jmp" | "j" => { let dest = parse_label(arg_tokens.next())?; if far { Op::Jump(dest) } else { Op::FarJump(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))?); } Op::Call(dest, args) } "ret" => { let mut args = vec![]; for t in arg_tokens { args.push(parse_rd(Some(t))?); } Op::Ret(args) } "rtn" | "fn" => { let dest = RoutineName(expect_string_atom(arg_tokens.next())?); Op::Routine(dest) } "skip" => { Op::Skip(parse_rd(arg_tokens.next())?) } "jmp.if" | "j.if" => { let dest = parse_label(arg_tokens.next())?; Op::JumpIf(parse_cond(&expect_string_atom(arg_tokens.next())?)?, dest) } "barrier" => { Op::Barrier(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), }) } "fault" => { Op::Fault(match arg_tokens.next() { None => None, Some(s) => Some(expect_string_atom(Some(s))?.into()), }) } "mov" | "ld" | "mv" => { Op::Mov( parse_wr(arg_tokens.next())?, parse_rd(arg_tokens.next())? ) } "cmp" => { Op::Cmp( parse_rd(arg_tokens.next())?, parse_rd(arg_tokens.next())? ) } "inc" => { Op::Inc( parse_wr(arg_tokens.next())? ) } "dec" => { Op::Dec( parse_wr(arg_tokens.next())? ) } other => { if let Some(label) = other.strip_prefix(':') { let label = Label::Named(label.to_string()); if far { Op::Label(label) } else { Op::FarLabel(label) } } else { return Err(Error::Parse(format!("Unknown instruction: {}", other).into())); } } }) }