diff --git a/crsn/src/asm/data/reg.rs b/crsn/src/asm/data/reg.rs index d9333b8..25d2d11 100644 --- a/crsn/src/asm/data/reg.rs +++ b/crsn/src/asm/data/reg.rs @@ -1,6 +1,6 @@ use std::fmt::{self, Display, Formatter}; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; /// Register name #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -34,6 +34,6 @@ pub fn parse_reg(name: &str) -> anyhow::Result { let val: u8 = rn.parse()?; Ok(Register::Gen(val)) } else { - Err(Error::Parse(format!("Bad reg name: {}", name).into()))? + Err(CrsnError::Parse(format!("Bad reg name: {}", name).into()))? } } diff --git a/crsn/src/asm/error.rs b/crsn/src/asm/error.rs index dc89b9e..8ee60d4 100644 --- a/crsn/src/asm/error.rs +++ b/crsn/src/asm/error.rs @@ -8,7 +8,7 @@ use crate::asm::instr::Cond; /// csn_asm unified error type #[derive(Error, Debug)] -pub enum Error { +pub enum CrsnError { #[error("S-expression syntax error: {0:?}")] PreParse(#[from] Box), #[error("Parse error: {0:?}")] diff --git a/crsn/src/asm/instr/cond.rs b/crsn/src/asm/instr/cond.rs index d3bc847..4da4ddf 100644 --- a/crsn/src/asm/instr/cond.rs +++ b/crsn/src/asm/instr/cond.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Display, Formatter}; use std::ops::Not; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; /// Condition flag #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] @@ -45,7 +45,7 @@ pub enum Cond { NotCarry, } -pub fn parse_cond(text: &str) -> Result { +pub fn parse_cond(text: &str) -> Result { Ok(match text.trim_end_matches('?') { "eq" | "=" | "==" => Cond::Equal, "ne" | "<>" | "!=" | "≠" => Cond::NotEqual, @@ -66,7 +66,7 @@ pub fn parse_cond(text: &str) -> Result { "ov" | "^" => Cond::Overflow, "nov" | "!ov" | "!^" => Cond::NotOverflow, _ => { - return Err(Error::Parse(format!("Unknown cond: {}", text).into())); + return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into())); } }) } diff --git a/crsn/src/asm/instr/flatten.rs b/crsn/src/asm/instr/flatten.rs index 6cc2baa..da6436f 100644 --- a/crsn/src/asm/instr/flatten.rs +++ b/crsn/src/asm/instr/flatten.rs @@ -3,17 +3,17 @@ use std::sync::atomic::AtomicU32; use crate::asm::data::{Rd, RdData}; use crate::asm::data::literal::{Label, Value}; -use crate::asm::error::{AsmError, Error}; +use crate::asm::error::{AsmError, CrsnError}; use crate::asm::instr::{Cond, Instr, Op, Routine}; use crate::builtin::defs::BuiltinOp; /// A trait for something that can turn into multiple instructions pub trait Flatten { - fn flatten(self, label_num: &AtomicU32) -> Result, Error>; + fn flatten(self, label_num: &AtomicU32) -> Result, CrsnError>; } impl Flatten for Instr { - fn flatten(self, label_num: &AtomicU32) -> Result, Error> { + fn flatten(self, label_num: &AtomicU32) -> Result, CrsnError> { let mut ops = vec![self.op]; if let Some(branches) = self.branches { @@ -22,7 +22,7 @@ impl Flatten for Instr { let end_lbl = Label::unique(label_num); for (cnt, (cond, branch)) in branches.into_iter().enumerate() { if labels.contains_key(&cond) { - return Err(Error::Asm(AsmError::ConditionalAlreadyUsed(cond))); + return Err(CrsnError::Asm(AsmError::ConditionalAlreadyUsed(cond))); } let next_lbl = if cnt == branch_count - 1 { @@ -49,7 +49,7 @@ impl Flatten for Instr { } impl Flatten for Routine { - fn flatten(self, label_num: &AtomicU32) -> Result, Error> { + fn flatten(self, label_num: &AtomicU32) -> Result, CrsnError> { let mut ops = vec![ BuiltinOp::Routine(self.name.clone()).into(), ]; @@ -65,7 +65,7 @@ impl Flatten for Routine { } /// Convert jumps to relative skips -fn numbered_labels_to_skips(ops: Vec) -> Result, Error> { +fn numbered_labels_to_skips(ops: Vec) -> Result, CrsnError> { let mut label_positions = HashMap::::new(); for (n, op) in ops.iter().enumerate() { if let Op::BuiltIn(BuiltinOp::Label(name @ Label::Numbered(_))) = op { @@ -85,7 +85,7 @@ fn numbered_labels_to_skips(ops: Vec) -> Result, Error> { let skip = *dest as isize - n as isize + skipped; cleaned.push(Op::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value))))); } else { - return Err(Error::Asm(AsmError::LabelNotDefined(target))); + return Err(CrsnError::Asm(AsmError::LabelNotDefined(target))); } } Op::BuiltIn(BuiltinOp::JumpIf(cond, target @ Label::Numbered(_))) => { @@ -93,7 +93,7 @@ fn numbered_labels_to_skips(ops: Vec) -> Result, Error> { let skip = *dest as isize - n as isize + skipped; cleaned.push(Op::BuiltIn(BuiltinOp::SkipIf(cond, Rd::new(RdData::Immediate(skip as Value))))); } else { - return Err(Error::Asm(AsmError::LabelNotDefined(target))); + return Err(CrsnError::Asm(AsmError::LabelNotDefined(target))); } } other => { diff --git a/crsn/src/asm/mod.rs b/crsn/src/asm/mod.rs index f41c510..faab7d8 100644 --- a/crsn/src/asm/mod.rs +++ b/crsn/src/asm/mod.rs @@ -10,7 +10,7 @@ pub mod parse; pub mod patches; /// Parse a program from string and assemble a low level instruction sequence from it. -pub fn assemble(source: &str, parsers: Arc>>) -> Result, error::Error> { +pub fn assemble(source: &str, parsers: Arc>>) -> Result, error::CrsnError> { let ops = parse::parse(source, &parsers)?; trace!("--- Compiled program ---"); diff --git a/crsn/src/asm/parse/mod.rs b/crsn/src/asm/parse/mod.rs index 27b7497..fe08f4e 100644 --- a/crsn/src/asm/parse/mod.rs +++ b/crsn/src/asm/parse/mod.rs @@ -3,7 +3,7 @@ use std::sync::atomic::AtomicU32; pub use parse_instr::parse_instructions; use parse_routines::parse_routines; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::{Flatten, Op, Routine}; use crate::asm::parse::sexp_expect::expect_list; use crate::module::CrsnExtension; @@ -17,7 +17,7 @@ mod parse_op; pub mod arg_parser; -pub fn parse(source: &str, parsers: &[Box]) -> Result, Error> { +pub fn parse(source: &str, parsers: &[Box]) -> Result, CrsnError> { let root = sexp::parse(source)?; let subs: Vec = parse_routines(expect_list(Some(root), true)?, parsers)?; diff --git a/crsn/src/asm/parse/parse_cond.rs b/crsn/src/asm/parse/parse_cond.rs index 8532cb5..177aa80 100644 --- a/crsn/src/asm/parse/parse_cond.rs +++ b/crsn/src/asm/parse/parse_cond.rs @@ -1,18 +1,18 @@ use sexp::Sexp; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::{Cond, cond, Instr}; use crate::asm::parse::parse_instr::parse_instructions; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::patches::TryRemove; use crate::module::CrsnExtension; -pub fn parse_cond_branch(tok: Sexp, parsers: &[Box]) -> Result<(Cond, Vec), Error> { +pub fn parse_cond_branch(tok: Sexp, parsers: &[Box]) -> Result<(Cond, Vec), CrsnError> { let mut list = expect_list(Some(tok), false)?; let kw = expect_string_atom(list.try_remove(0))?; if !kw.ends_with('?') { - return Err(Error::Parse(format!("Condition must end with '?': {}", kw).into())); + return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into())); } Ok((cond::parse_cond(&kw)?, parse_instructions(list, parsers)?)) diff --git a/crsn/src/asm/parse/parse_data.rs b/crsn/src/asm/parse/parse_data.rs index 0569f51..ce2f5dc 100644 --- a/crsn/src/asm/parse/parse_data.rs +++ b/crsn/src/asm/parse/parse_data.rs @@ -4,21 +4,21 @@ use sexp::{Atom, Sexp}; use crate::asm::data::{DataDisp, Rd, RdData, reg, Wr, WrData}; use crate::asm::data::literal::Label; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::parse::sexp_expect::expect_string_atom; /// Parse a label -pub fn parse_label(name: Option) -> Result { +pub fn parse_label(name: Option) -> Result { let name = expect_string_atom(name)?; Ok(Label::Named(name.trim_start_matches(':').into())) } /// Parse data disposition (address/value, without the read/write restriction) -pub fn parse_data_disp(tok: Option) -> Result { +pub fn parse_data_disp(tok: Option) -> Result { let tok = if let Some(tok) = tok { tok } else { - return Err(Error::Parse("Expected data disposition token".into())); + return Err(CrsnError::Parse("Expected data disposition token".into())); }; // TODO implement masks @@ -41,7 +41,7 @@ pub fn parse_data_disp(tok: Option) -> Result { } } _ => { - Err(Error::Parse(format!("bad data disp: {:?}", tok).into())) + Err(CrsnError::Parse(format!("bad data disp: {:?}", tok).into())) } } } diff --git a/crsn/src/asm/parse/parse_instr.rs b/crsn/src/asm/parse/parse_instr.rs index ccaa022..0025de7 100644 --- a/crsn/src/asm/parse/parse_instr.rs +++ b/crsn/src/asm/parse/parse_instr.rs @@ -1,6 +1,6 @@ use sexp::Sexp; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::Instr; use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::parse_cond::parse_cond_branch; @@ -10,7 +10,7 @@ use crate::module::CrsnExtension; use super::parse_op::parse_op; -pub fn parse_instructions(instrs: Vec, parsers: &[Box]) -> Result, Error> { +pub fn parse_instructions(instrs: Vec, parsers: &[Box]) -> Result, CrsnError> { let mut parsed = vec![]; for expr in instrs { let tokens = expect_list(Some(expr), false)?; diff --git a/crsn/src/asm/parse/parse_op.rs b/crsn/src/asm/parse/parse_op.rs index 2a24057..3b0c07d 100644 --- a/crsn/src/asm/parse/parse_op.rs +++ b/crsn/src/asm/parse/parse_op.rs @@ -1,10 +1,10 @@ -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::Op; use crate::asm::parse::arg_parser::ArgParser; use crate::builtin::parse::BuiltinOps; use crate::module::{CrsnExtension, ParseOpRes}; -pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box]) -> Result { +pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box]) -> Result { // Include built-in instructions let builtins = [BuiltinOps::new()]; @@ -23,5 +23,5 @@ pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box, parsers: &[Box]) -> Result, Error> { +pub fn parse_routines(routines: Vec, parsers: &[Box]) -> Result, CrsnError> { let mut parsed = vec![]; for rt in routines { let mut def = expect_list(Some(rt), false)?; diff --git a/crsn/src/asm/parse/sexp_expect.rs b/crsn/src/asm/parse/sexp_expect.rs index 55c84e4..c0d8969 100644 --- a/crsn/src/asm/parse/sexp_expect.rs +++ b/crsn/src/asm/parse/sexp_expect.rs @@ -1,16 +1,16 @@ use sexp::{Atom, Sexp}; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; -pub fn expect_list(expr: Option, allow_empty: bool) -> Result, Error> { +pub fn expect_list(expr: Option, allow_empty: bool) -> Result, CrsnError> { if let Some(expr) = expr { match &expr { Sexp::Atom(_) => { - return Err(Error::ParseIn("Expected a list".into(), expr)); + return Err(CrsnError::ParseIn("Expected a list".into(), expr)); } Sexp::List(list) => { if !allow_empty && list.is_empty() { - return Err(Error::ParseIn("Routine: Empty list".into(), expr)); + return Err(CrsnError::ParseIn("Routine: Empty list".into(), expr)); } if let Sexp::List(list) = expr { @@ -22,10 +22,10 @@ pub fn expect_list(expr: Option, allow_empty: bool) -> Result, E } } - Err(Error::Parse("Expected a list, got nothing".into())) + Err(CrsnError::Parse("Expected a list, got nothing".into())) } -pub fn expect_atom(expr: Option) -> Result { +pub fn expect_atom(expr: Option) -> Result { if let Some(expr) = expr { match &expr { Sexp::Atom(_atom) => { @@ -36,18 +36,18 @@ pub fn expect_atom(expr: Option) -> Result { } } Sexp::List(_) => { - return Err(Error::ParseIn("Expected atom got list".into(), expr)); + return Err(CrsnError::ParseIn("Expected atom got list".into(), expr)); } } } - Err(Error::Parse("Expected atom, got nothing".into())) + Err(CrsnError::Parse("Expected atom, got nothing".into())) } -pub fn expect_string_atom(expr: Option) -> Result { +pub fn expect_string_atom(expr: Option) -> Result { match expect_atom(expr) { Ok(Atom::S(s)) => Ok(s), - Ok(atom) => Err(Error::ParseIn("Expected string atom".into(), Sexp::Atom(atom))), + Ok(atom) => Err(CrsnError::ParseIn("Expected string atom".into(), Sexp::Atom(atom))), Err(e) => Err(e), } } diff --git a/crsn/src/builtin/parse.rs b/crsn/src/builtin/parse.rs index 7ae516d..ff34ec9 100644 --- a/crsn/src/builtin/parse.rs +++ b/crsn/src/builtin/parse.rs @@ -1,7 +1,7 @@ use sexp::{Atom, Sexp}; use crate::asm::data::literal::{Label, RoutineName}; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::cond::parse_cond; use crate::asm::instr::Op; use crate::asm::parse::arg_parser::ArgParser; @@ -28,7 +28,7 @@ impl CrsnExtension for BuiltinOps { "builtin" } - fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result, Error> { + fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result, CrsnError> { Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword { "nop" => { BuiltinOp::Nop diff --git a/crsn/src/module/mod.rs b/crsn/src/module/mod.rs index 5d023b8..7dca685 100644 --- a/crsn/src/module/mod.rs +++ b/crsn/src/module/mod.rs @@ -4,7 +4,7 @@ pub use eval_res::EvalRes; use crate::asm::data::literal::Value; use crate::asm::data::Mask; -use crate::asm::error::Error; +use crate::asm::error::CrsnError; use crate::asm::instr::Op; use crate::asm::parse::arg_parser::ArgParser; use crate::runtime::fault::Fault; @@ -23,7 +23,7 @@ pub enum ParseOpRes { impl ParseOpRes { /// Helper to construct an extension op - pub fn parsed(op : impl OpTrait) -> Self { + pub fn ext(op : impl OpTrait) -> Self { Self::Parsed(Op::Ext(Box::new(op))) } } @@ -41,7 +41,7 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static { /// the argument list and either return Ok or Err. /// /// If the instruction keyword is not recognized, return Unknown with the unchanged argument list. - fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result, Error>; + fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result, CrsnError>; /// Drop an object referenced by a handle fn drop_obj(&self, diff --git a/crsn_arith/src/lib.rs b/crsn_arith/src/lib.rs index e2f4f86..427a488 100644 --- a/crsn_arith/src/lib.rs +++ b/crsn_arith/src/lib.rs @@ -1,6 +1,27 @@ -pub use parse::ArithOps; +use crsn::module::{CrsnExtension, ParseOpRes}; +use crsn::asm::parse::arg_parser::ArgParser; +use crsn::asm::error::CrsnError; +use crsn::asm::instr::Op; mod defs; mod parse; mod exec; +#[derive(Debug, Clone)] +pub struct ArithOps; + +impl ArithOps { + pub fn new() -> Box { + Box::new(Self) + } +} + +impl CrsnExtension for ArithOps { + fn name(&self) -> &'static str { + "arith" + } + + fn parse_op(&self, keyword: &str, args: ArgParser) -> Result, CrsnError> { + parse::parse(keyword, args) + } +} diff --git a/crsn_arith/src/parse.rs b/crsn_arith/src/parse.rs index 316d216..c5f1284 100644 --- a/crsn_arith/src/parse.rs +++ b/crsn_arith/src/parse.rs @@ -1,455 +1,437 @@ use crsn::asm::data::{Rd, Wr}; -use crsn::asm::error::Error; +use crsn::asm::error::CrsnError; use crsn::asm::instr::Op; use crsn::asm::parse::arg_parser::ArgParser; -use crsn::module::{CrsnExtension, ParseOpRes}; +use crsn::module::{ParseOpRes}; use crate::defs::ArithOp; -#[derive(Debug, Clone)] -pub struct ArithOps { - _internal: () -} - -impl ArithOps { - pub fn new() -> Box { - Box::new(Self { - _internal: () - }) - } -} +pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result, CrsnError> { + Ok(ParseOpRes::ext(match keyword { + "cmp" => { + ArithOp::Compare { + a: args.next_rd()?, + b: args.next_rd()?, + } + } -impl CrsnExtension for ArithOps { - fn name(&self) -> &'static str { - "arith" - } + "tst" => { + let arg = args.next_rd()?; + ArithOp::Test { a: arg } + } - fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result, Error> { - Ok(ParseOpRes::parsed(match keyword { - "cmp" => { - ArithOp::Compare { - a: args.next_rd()?, - b: args.next_rd()?, - } + "inc" => { + let dst = args.next_wr()?; + ArithOp::Add { + dst, + a: dst.as_rd(), + b: Rd::immediate(1), } + } - "tst" => { - let arg = args.next_rd()?; - ArithOp::Test { a: arg } + "dec" => { + let dst = args.next_wr()?; + ArithOp::Sub { + dst, + a: dst.as_rd(), + b: Rd::immediate(1), } + } - "inc" => { - let dst = args.next_wr()?; - ArithOp::Add { - dst, - a: dst.as_rd(), - b: Rd::immediate(1), + "add" => { + match args.len() { + 3 => { + ArithOp::Add { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, + } } - } - - "dec" => { - let dst = args.next_wr()?; - ArithOp::Sub { - dst, - a: dst.as_rd(), - b: Rd::immediate(1), + 2 => { + let dst = args.next_wr()?; + ArithOp::Add { + dst, + a: dst.as_rd(), + b: args.next_rd()?, + } + } + _ => { + return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into())); } } + } - "add" => { - match args.len() { - 3 => { - ArithOp::Add { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Add { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("Add requires 2 or 3 arguments".into())); + "sub" => { + match args.len() { + 3 => { + ArithOp::Sub { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::Sub { + dst, + a: dst.as_rd(), + b: args.next_rd()?, } } + _ => { + return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into())); + } } + } - "sub" => { - match args.len() { - 3 => { - ArithOp::Sub { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Sub { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("Sub requires 2 or 3 arguments".into())); + "mul" => { + match args.len() { + 3 => { + ArithOp::Mul { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::Mul { + dst, + a: dst.as_rd(), + b: args.next_rd()?, } } + _ => { + return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into())); + } } + } - "mul" => { - match args.len() { - 3 => { - ArithOp::Mul { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Mul { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("Mul requires 2 or 3 arguments".into())); + "divr" => { + match args.len() { + 3 => { + let dst = args.next_wr()?; + let rem = args.next_wr()?; + let div = args.next_rd()?; + ArithOp::Div { + dst, + rem, + a: dst.as_rd(), + div, } } + 4 => { + ArithOp::Div { + dst: args.next_wr()?, + rem: args.next_wr()?, + a: args.next_rd()?, + div: args.next_rd()?, + } + } + _ => { + return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into())); + } } + } - "divr" => { - match args.len() { - 3 => { - let dst = args.next_wr()?; - let rem = args.next_wr()?; - let div = args.next_rd()?; - ArithOp::Div { - dst, - rem, - a: dst.as_rd(), - div, - } - } - 4 => { - ArithOp::Div { - dst: args.next_wr()?, - rem: args.next_wr()?, - a: args.next_rd()?, - div: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("DivR requires 3 or 4 arguments".into())); + "div" => { + match args.len() { + 3 => { + ArithOp::Div { + dst: args.next_wr()?, + rem: Wr::discard(), + a: args.next_rd()?, + div: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + let div = args.next_rd()?; + ArithOp::Div { + dst, + rem: Wr::discard(), + a: dst.as_rd(), + div, } } + _ => { + return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into())); + } } + } - "div" => { - match args.len() { - 3 => { - ArithOp::Div { - dst: args.next_wr()?, - rem: Wr::discard(), - a: args.next_rd()?, - div: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - let div = args.next_rd()?; - ArithOp::Div { - dst, - rem: Wr::discard(), - a: dst.as_rd(), - div, - } - } - _ => { - return Err(Error::Parse("Div requires 2 or 3 arguments".into())); + "mod" => { + match args.len() { + 3 => { + ArithOp::Mod { + dst: args.next_wr()?, + a: args.next_rd()?, + div: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + let div = args.next_rd()?; + ArithOp::Mod { + dst, + a: dst.as_rd(), + div, } } + _ => { + return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into())); + } } + } - "mod" => { - match args.len() { - 3 => { - ArithOp::Mod { - dst: args.next_wr()?, - a: args.next_rd()?, - div: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - let div = args.next_rd()?; - ArithOp::Mod { - dst, - a: dst.as_rd(), - div, - } - } - _ => { - return Err(Error::Parse("Mod requires 2 or 3 arguments".into())); + "and" => { + match args.len() { + 3 => { + ArithOp::And { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::And { + dst, + a: dst.as_rd(), + b: args.next_rd()?, } } + _ => { + return Err(CrsnError::Parse("And requires 2 or 3 arguments".into())); + } } + } - "and" => { - match args.len() { - 3 => { - ArithOp::And { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::And { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("And requires 2 or 3 arguments".into())); + "or" => { + match args.len() { + 3 => { + ArithOp::Or { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, } } + 2 => { + let dst = args.next_wr()?; + ArithOp::Or { + dst, + a: dst.as_rd(), + b: args.next_rd()?, + } + } + _ => { + return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into())); + } } + } - "or" => { - match args.len() { - 3 => { - ArithOp::Or { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Or { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("Or requires 2 or 3 arguments".into())); + "xor" => { + match args.len() { + 3 => { + ArithOp::Xor { + dst: args.next_wr()?, + a: args.next_rd()?, + b: args.next_rd()?, } } + 2 => { + let dst = args.next_wr()?; + ArithOp::Xor { + dst, + a: dst.as_rd(), + b: args.next_rd()?, + } + } + _ => { + return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into())); + } } + } - "xor" => { - match args.len() { - 3 => { - ArithOp::Xor { - dst: args.next_wr()?, - a: args.next_rd()?, - b: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Xor { - dst, - a: dst.as_rd(), - b: args.next_rd()?, - } - } - _ => { - return Err(Error::Parse("Xor requires 2 or 3 arguments".into())); + "cpl" => { + match args.len() { + 2 => { + ArithOp::Cpl { + dst: args.next_wr()?, + a: args.next_rd()?, + } + } + 1 => { + let dst = args.next_wr()?; + ArithOp::Cpl { + dst, + a: dst.as_rd(), } } + _ => { + return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into())); + } } + } - "cpl" => { - match args.len() { - 2 => { - ArithOp::Cpl { - dst: args.next_wr()?, - a: args.next_rd()?, - } + "rol" => { + match args.len() { + 3 => { + ArithOp::Rol { + dst: args.next_wr()?, + a: args.next_rd()?, + n: args.next_rd()?, } - 1 => { - let dst = args.next_wr()?; - ArithOp::Cpl { - dst, - a: dst.as_rd(), - } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::Rol { + dst, + a: dst.as_rd(), + n: args.next_rd()?, } - _ => { - return Err(Error::Parse("Cpl requires 1 or 2 arguments".into())); + } + 1 => { + let dst = args.next_wr()?; + ArithOp::Rol { + dst, + a: dst.as_rd(), + n: Rd::immediate(1), } } + _ => { + return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into())); + } } + } - "rol" => { - match args.len() { - 3 => { - ArithOp::Rol { - dst: args.next_wr()?, - a: args.next_rd()?, - n: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Rol { - dst, - a: dst.as_rd(), - n: args.next_rd()?, - } - } - 1 => { - let dst = args.next_wr()?; - ArithOp::Rol { - dst, - a: dst.as_rd(), - n: Rd::immediate(1), - } - } - _ => { - return Err(Error::Parse("Rol requires 1, 2 or 3 arguments".into())); + "ror" => { + match args.len() { + 3 => { + ArithOp::Ror { + dst: args.next_wr()?, + a: args.next_rd()?, + n: args.next_rd()?, } } - } - - "ror" => { - match args.len() { - 3 => { - ArithOp::Ror { - dst: args.next_wr()?, - a: args.next_rd()?, - n: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Ror { - dst, - a: dst.as_rd(), - n: args.next_rd()?, - } - } - 1 => { - let dst = args.next_wr()?; - ArithOp::Ror { - dst, - a: dst.as_rd(), - n: Rd::immediate(1), - } - } - _ => { - return Err(Error::Parse("Ror requires 1, 2 or 3 arguments".into())); + 2 => { + let dst = args.next_wr()?; + ArithOp::Ror { + dst, + a: dst.as_rd(), + n: args.next_rd()?, + } + } + 1 => { + let dst = args.next_wr()?; + ArithOp::Ror { + dst, + a: dst.as_rd(), + n: Rd::immediate(1), } } + _ => { + return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into())); + } } + } - "lsl" | "asl" => { - match args.len() { - 3 => { - ArithOp::Lsl { - dst: args.next_wr()?, - a: args.next_rd()?, - n: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Lsl { - dst, - a: dst.as_rd(), - n: args.next_rd()?, - } - } - 1 => { - let dst = args.next_wr()?; - ArithOp::Lsl { - dst, - a: dst.as_rd(), - n: Rd::immediate(1), - } - } - _ => { - return Err(Error::Parse("Lsl requires 1, 2 or 3 arguments".into())); + "lsl" | "asl" => { + match args.len() { + 3 => { + ArithOp::Lsl { + dst: args.next_wr()?, + a: args.next_rd()?, + n: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::Lsl { + dst, + a: dst.as_rd(), + n: args.next_rd()?, } } + 1 => { + let dst = args.next_wr()?; + ArithOp::Lsl { + dst, + a: dst.as_rd(), + n: Rd::immediate(1), + } + } + _ => { + return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into())); + } } + } - "lsr" => { - match args.len() { - 3 => { - ArithOp::Lsr { - dst: args.next_wr()?, - a: args.next_rd()?, - n: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Lsr { - dst, - a: dst.as_rd(), - n: args.next_rd()?, - } - } - 1 => { - let dst = args.next_wr()?; - ArithOp::Lsr { - dst, - a: dst.as_rd(), - n: Rd::immediate(1), - } - } - _ => { - return Err(Error::Parse("Lsr requires 1, 2 or 3 arguments".into())); + "lsr" => { + match args.len() { + 3 => { + ArithOp::Lsr { + dst: args.next_wr()?, + a: args.next_rd()?, + n: args.next_rd()?, + } + } + 2 => { + let dst = args.next_wr()?; + ArithOp::Lsr { + dst, + a: dst.as_rd(), + n: args.next_rd()?, + } + } + 1 => { + let dst = args.next_wr()?; + ArithOp::Lsr { + dst, + a: dst.as_rd(), + n: Rd::immediate(1), } } + _ => { + return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into())); + } } + } - "asr" => { - match args.len() { - 3 => { - ArithOp::Asr { - dst: args.next_wr()?, - a: args.next_rd()?, - n: args.next_rd()?, - } - } - 2 => { - let dst = args.next_wr()?; - ArithOp::Asr { - dst, - a: dst.as_rd(), - n: args.next_rd()?, - } - } - 1 => { - let dst = args.next_wr()?; - ArithOp::Asr { - dst, - a: dst.as_rd(), - n: Rd::immediate(1), - } - } - _ => { - return Err(Error::Parse("Asr requires 1, 2 or 3 arguments".into())); + "asr" => { + match args.len() { + 3 => { + ArithOp::Asr { + dst: args.next_wr()?, + a: args.next_rd()?, + n: args.next_rd()?, } } + 2 => { + let dst = args.next_wr()?; + ArithOp::Asr { + dst, + a: dst.as_rd(), + n: args.next_rd()?, + } + } + 1 => { + let dst = args.next_wr()?; + ArithOp::Asr { + dst, + a: dst.as_rd(), + n: Rd::immediate(1), + } + } + _ => { + return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into())); + } } + } - _other => { - return Ok(ParseOpRes::Unknown(args)); - } - })) - } + _other => { + return Ok(ParseOpRes::Unknown(args)); + } + })) } + diff --git a/crsn_stacks/src/exec.rs b/crsn_stacks/src/exec.rs index bd4f8c9..6cb71a4 100644 --- a/crsn_stacks/src/exec.rs +++ b/crsn_stacks/src/exec.rs @@ -67,7 +67,7 @@ impl OpTrait for StackOp { // } -pub(crate) fn drop_stack(state: &mut RunState, handle: Value) -> Result, Fault> { +pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result, Fault> { let stacks: &mut Stacks = state.ext_mut(); Ok(stacks.store.remove(&handle).map(|_| ())) } diff --git a/crsn_stacks/src/lib.rs b/crsn_stacks/src/lib.rs index e182b9f..78b8c7f 100644 --- a/crsn_stacks/src/lib.rs +++ b/crsn_stacks/src/lib.rs @@ -1,6 +1,27 @@ -pub use parse::StackOps; +use crsn::module::{CrsnExtension, ParseOpRes}; +use crsn::asm::parse::arg_parser::ArgParser; +use crsn::asm::instr::Op; +use crsn::asm::error::CrsnError; mod defs; mod parse; mod exec; +#[derive(Debug, Clone)] +pub struct StackOps; + +impl StackOps { + pub fn new() -> Box { + Box::new(Self) + } +} + +impl CrsnExtension for StackOps { + fn name(&self) -> &'static str { + "stacks" + } + + fn parse_op(&self, keyword: &str, args: ArgParser) -> Result, CrsnError> { + parse::parse(keyword, args) + } +} diff --git a/crsn_stacks/src/parse.rs b/crsn_stacks/src/parse.rs index ee5bbbf..a149859 100644 --- a/crsn_stacks/src/parse.rs +++ b/crsn_stacks/src/parse.rs @@ -1,61 +1,37 @@ -use crsn::asm::data::literal::Value; -use crsn::asm::error::Error; + +use crsn::asm::error::CrsnError; use crsn::asm::instr::Op; use crsn::asm::parse::arg_parser::ArgParser; -use crsn::module::{CrsnExtension, ParseOpRes}; -use crsn::runtime::fault::Fault; -use crsn::runtime::run_thread::{RunState, ThreadInfo}; +use crsn::module::{ParseOpRes}; -use crate::defs::StackOp; -#[derive(Debug, Clone)] -pub struct StackOps { - _internal: () -} -impl StackOps { - pub fn new() -> Box { - Box::new(Self { - _internal: () - }) - } -} - -impl CrsnExtension for StackOps { - fn name(&self) -> &'static str { - "stacks" - } - - fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result, Error> { - Ok(ParseOpRes::parsed(match keyword { - "stack" => { - StackOp::NewStack { - dst: args.next_wr()?, - } - } +use crate::defs::StackOp; - "push" => { - StackOp::Push { - obj: args.next_rdobj()?, - src: args.next_rd()?, - } +pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result, CrsnError> { + Ok(ParseOpRes::ext(match keyword { + "stack" => { + StackOp::NewStack { + dst: args.next_wr()?, } + } - "pop" => { - StackOp::Pop { - dst: args.next_wr()?, - obj: args.next_rdobj()?, - } + "push" => { + StackOp::Push { + obj: args.next_rdobj()?, + src: args.next_rd()?, } + } - _other => { - return Ok(ParseOpRes::Unknown(args)); + "pop" => { + StackOp::Pop { + dst: args.next_wr()?, + obj: args.next_rdobj()?, } - })) - } + } - fn drop_obj(&self, _ti: &ThreadInfo, state: &mut RunState, handle: Value) -> Result, Fault> - { - crate::exec::drop_stack(state, handle) - } + _other => { + return Ok(ParseOpRes::Unknown(args)); + } + })) }