use crsn::asm::error::CrsnError; use crsn::asm::instr::op::OpKind; use crsn::asm::parse::arg_parser::TokenParser; use crsn::module::ParseRes; use crsn::sexp::{SourcePosition, Sexp, Atom}; use crate::defs::{BufOps, BufValue, BufIoMode}; use crsn::asm::data::Rd; use crsn::asm::parse::parse_data::parse_rd; use crsn::asm::data::literal::Value; pub const BUF_IOMODE_STACK : Value = 1; pub const BUF_IOMODE_REVERSE_STACK : Value = 2; pub const BUF_IOMODE_QUEUE : Value = 3; pub const BUF_IOMODE_REVERSE_QUEUE : Value = 4; pub(crate) fn parse<'a>(_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result, CrsnError> { Ok(ParseRes::ext(match keyword { "mkbf" => { let dst = args.next_wr()?; let value = match args.next() { None => { BufValue::Zeros(Rd::new_imm(0)) } Some(tok @ Sexp::Atom(Atom::S(_), _)) | Some(tok @ Sexp::Atom(Atom::I(_), _)) | Some(tok @ Sexp::Atom(Atom::U(_), _)) => { BufValue::Zeros(parse_rd(tok, args.pcx)?) } Some(Sexp::Atom(Atom::QS(s), _)) => { BufValue::Chars(s) } Some(Sexp::List(list, _)) => { let mut vals = vec![]; for v in list { vals.push(parse_rd(v, args.pcx)?); } BufValue::Values(vals) } Some(other) => { return Err(CrsnError::Parse("Expected quoted string or a tuple of values".into(), other.pos().clone())); } }; BufOps::New { dst, value } } "bfio" => { let obj = args.next_rdobj()?; let (mode, modepos) = args.next_value()?; BufOps::SetIoMode { obj, mode: match mode { BUF_IOMODE_STACK => BufIoMode::Stack, BUF_IOMODE_REVERSE_STACK => BufIoMode::ReverseStack, BUF_IOMODE_QUEUE => BufIoMode::Queue, BUF_IOMODE_REVERSE_QUEUE => BufIoMode::ReverseQueue, _ => return Err(CrsnError::Parse("Bad buffer iomode".into(), modepos)) } } } "bfrd" => { let dst = args.next_wr()?; let obj = args.next_rdobj()?; let idx = args.next_rd()?; BufOps::Read { dst, obj, idx } } "bfwr" => { let obj = args.next_rdobj()?; let idx = args.next_rd()?; let value = args.next_rd()?; BufOps::Write { obj, idx, value } } "bfcas" => { let obj = args.next_rdobj()?; let idx = args.next_rd()?; let expected = args.next_rd()?; let src = args.next_rd()?; BufOps::CompareSwap { obj, idx, expected, src } } "bfsz" => { let dst = args.next_wr()?; let obj = args.next_rdobj()?; BufOps::GetLen { dst, obj } } "bfins" => { let obj = args.next_rdobj()?; let idx = args.next_rd()?; let value = args.next_rd()?; BufOps::Insert { obj, idx, value } } "bfrm" => { let dst = args.next_wr()?; let obj = args.next_rdobj()?; let idx = args.next_rd()?; BufOps::Remove { dst, obj, idx } } "bfpush" => { BufOps::Push { obj: args.next_rdobj()?, src: args.next_rd()?, } } "bfpop" => { BufOps::Pop { dst: args.next_wr()?, obj: args.next_rdobj()?, } } "bfrpush" => { BufOps::Insert { obj: args.next_rdobj()?, idx: Rd::new_imm(0), value: args.next_rd()?, } } "bfrpop" => { BufOps::Remove { dst: args.next_wr()?, obj: args.next_rdobj()?, idx: Rd::new_imm(0), } } "bfrsz" => { BufOps::Resize { obj: args.next_rdobj()?, len: args.next_rd()?, } } "bfrev" => { BufOps::Reverse { obj: args.next_rdobj()?, } } "bfapp" => { BufOps::AppendBuf { obj: args.next_rdobj()?, obj2: args.next_rdobj()?, } } "bfprep" => { BufOps::PrependBuf { obj: args.next_rdobj()?, obj2: args.next_rdobj()?, } } _other => { return Ok(ParseRes::Unknown(args)); } })) }