pull/21/head
Ondřej Hruška 4 years ago
parent 2269d759c6
commit b7345144e0
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 4
      crsn/src/asm/data/reg.rs
  2. 2
      crsn/src/asm/error.rs
  3. 6
      crsn/src/asm/instr/cond.rs
  4. 16
      crsn/src/asm/instr/flatten.rs
  5. 2
      crsn/src/asm/mod.rs
  6. 4
      crsn/src/asm/parse/mod.rs
  7. 6
      crsn/src/asm/parse/parse_cond.rs
  8. 10
      crsn/src/asm/parse/parse_data.rs
  9. 4
      crsn/src/asm/parse/parse_instr.rs
  10. 6
      crsn/src/asm/parse/parse_op.rs
  11. 4
      crsn/src/asm/parse/parse_routines.rs
  12. 20
      crsn/src/asm/parse/sexp_expect.rs
  13. 4
      crsn/src/builtin/parse.rs
  14. 6
      crsn/src/module/mod.rs
  15. 23
      crsn_arith/src/lib.rs
  16. 738
      crsn_arith/src/parse.rs
  17. 2
      crsn_stacks/src/exec.rs
  18. 23
      crsn_stacks/src/lib.rs
  19. 72
      crsn_stacks/src/parse.rs

@ -1,6 +1,6 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use crate::asm::error::Error; use crate::asm::error::CrsnError;
/// Register name /// Register name
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
@ -34,6 +34,6 @@ pub fn parse_reg(name: &str) -> anyhow::Result<Register> {
let val: u8 = rn.parse()?; let val: u8 = rn.parse()?;
Ok(Register::Gen(val)) Ok(Register::Gen(val))
} else { } else {
Err(Error::Parse(format!("Bad reg name: {}", name).into()))? Err(CrsnError::Parse(format!("Bad reg name: {}", name).into()))?
} }
} }

@ -8,7 +8,7 @@ use crate::asm::instr::Cond;
/// csn_asm unified error type /// csn_asm unified error type
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum CrsnError {
#[error("S-expression syntax error: {0:?}")] #[error("S-expression syntax error: {0:?}")]
PreParse(#[from] Box<sexp::Error>), PreParse(#[from] Box<sexp::Error>),
#[error("Parse error: {0:?}")] #[error("Parse error: {0:?}")]

@ -1,7 +1,7 @@
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::ops::Not; use std::ops::Not;
use crate::asm::error::Error; use crate::asm::error::CrsnError;
/// Condition flag /// Condition flag
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
@ -45,7 +45,7 @@ pub enum Cond {
NotCarry, NotCarry,
} }
pub fn parse_cond(text: &str) -> Result<Cond, Error> { pub fn parse_cond(text: &str) -> Result<Cond, CrsnError> {
Ok(match text.trim_end_matches('?') { Ok(match text.trim_end_matches('?') {
"eq" | "=" | "==" => Cond::Equal, "eq" | "=" | "==" => Cond::Equal,
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual, "ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
@ -66,7 +66,7 @@ pub fn parse_cond(text: &str) -> Result<Cond, Error> {
"ov" | "^" => Cond::Overflow, "ov" | "^" => Cond::Overflow,
"nov" | "!ov" | "!^" => Cond::NotOverflow, "nov" | "!ov" | "!^" => Cond::NotOverflow,
_ => { _ => {
return Err(Error::Parse(format!("Unknown cond: {}", text).into())); return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into()));
} }
}) })
} }

@ -3,17 +3,17 @@ use std::sync::atomic::AtomicU32;
use crate::asm::data::{Rd, RdData}; use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::{Label, Value}; 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::asm::instr::{Cond, Instr, Op, Routine};
use crate::builtin::defs::BuiltinOp; use crate::builtin::defs::BuiltinOp;
/// A trait for something that can turn into multiple instructions /// A trait for something that can turn into multiple instructions
pub trait Flatten { pub trait Flatten {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error>; fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
} }
impl Flatten for Instr { impl Flatten for Instr {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error> { fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
let mut ops = vec![self.op]; let mut ops = vec![self.op];
if let Some(branches) = self.branches { if let Some(branches) = self.branches {
@ -22,7 +22,7 @@ impl Flatten for Instr {
let end_lbl = Label::unique(label_num); let end_lbl = Label::unique(label_num);
for (cnt, (cond, branch)) in branches.into_iter().enumerate() { for (cnt, (cond, branch)) in branches.into_iter().enumerate() {
if labels.contains_key(&cond) { 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 { let next_lbl = if cnt == branch_count - 1 {
@ -49,7 +49,7 @@ impl Flatten for Instr {
} }
impl Flatten for Routine { impl Flatten for Routine {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error> { fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
let mut ops = vec![ let mut ops = vec![
BuiltinOp::Routine(self.name.clone()).into(), BuiltinOp::Routine(self.name.clone()).into(),
]; ];
@ -65,7 +65,7 @@ impl Flatten for Routine {
} }
/// Convert jumps to relative skips /// Convert jumps to relative skips
fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> { fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, CrsnError> {
let mut label_positions = HashMap::<Label, usize>::new(); let mut label_positions = HashMap::<Label, usize>::new();
for (n, op) in ops.iter().enumerate() { for (n, op) in ops.iter().enumerate() {
if let Op::BuiltIn(BuiltinOp::Label(name @ Label::Numbered(_))) = op { if let Op::BuiltIn(BuiltinOp::Label(name @ Label::Numbered(_))) = op {
@ -85,7 +85,7 @@ fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> {
let skip = *dest as isize - n as isize + skipped; let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value))))); cleaned.push(Op::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value)))));
} else { } else {
return Err(Error::Asm(AsmError::LabelNotDefined(target))); return Err(CrsnError::Asm(AsmError::LabelNotDefined(target)));
} }
} }
Op::BuiltIn(BuiltinOp::JumpIf(cond, target @ Label::Numbered(_))) => { Op::BuiltIn(BuiltinOp::JumpIf(cond, target @ Label::Numbered(_))) => {
@ -93,7 +93,7 @@ fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> {
let skip = *dest as isize - n as isize + skipped; let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::BuiltIn(BuiltinOp::SkipIf(cond, Rd::new(RdData::Immediate(skip as Value))))); cleaned.push(Op::BuiltIn(BuiltinOp::SkipIf(cond, Rd::new(RdData::Immediate(skip as Value)))));
} else { } else {
return Err(Error::Asm(AsmError::LabelNotDefined(target))); return Err(CrsnError::Asm(AsmError::LabelNotDefined(target)));
} }
} }
other => { other => {

@ -10,7 +10,7 @@ pub mod parse;
pub mod patches; pub mod patches;
/// Parse a program from string and assemble a low level instruction sequence from it. /// Parse a program from string and assemble a low level instruction sequence from it.
pub fn assemble(source: &str, parsers: Arc<Vec<Box<dyn CrsnExtension>>>) -> Result<Arc<Program>, error::Error> { pub fn assemble(source: &str, parsers: Arc<Vec<Box<dyn CrsnExtension>>>) -> Result<Arc<Program>, error::CrsnError> {
let ops = parse::parse(source, &parsers)?; let ops = parse::parse(source, &parsers)?;
trace!("--- Compiled program ---"); trace!("--- Compiled program ---");

@ -3,7 +3,7 @@ use std::sync::atomic::AtomicU32;
pub use parse_instr::parse_instructions; pub use parse_instr::parse_instructions;
use parse_routines::parse_routines; 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::instr::{Flatten, Op, Routine};
use crate::asm::parse::sexp_expect::expect_list; use crate::asm::parse::sexp_expect::expect_list;
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
@ -17,7 +17,7 @@ mod parse_op;
pub mod arg_parser; pub mod arg_parser;
pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, Error> { pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, CrsnError> {
let root = sexp::parse(source)?; let root = sexp::parse(source)?;
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?; let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;

@ -1,18 +1,18 @@
use sexp::Sexp; use sexp::Sexp;
use crate::asm::error::Error; use crate::asm::error::CrsnError;
use crate::asm::instr::{Cond, cond, Instr}; use crate::asm::instr::{Cond, cond, Instr};
use crate::asm::parse::parse_instr::parse_instructions; use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove; use crate::asm::patches::TryRemove;
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Vec<Instr>), Error> { pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Vec<Instr>), CrsnError> {
let mut list = expect_list(Some(tok), false)?; let mut list = expect_list(Some(tok), false)?;
let kw = expect_string_atom(list.try_remove(0))?; let kw = expect_string_atom(list.try_remove(0))?;
if !kw.ends_with('?') { 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)?)) Ok((cond::parse_cond(&kw)?, parse_instructions(list, parsers)?))

@ -4,21 +4,21 @@ use sexp::{Atom, Sexp};
use crate::asm::data::{DataDisp, Rd, RdData, reg, Wr, WrData}; use crate::asm::data::{DataDisp, Rd, RdData, reg, Wr, WrData};
use crate::asm::data::literal::Label; 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; use crate::asm::parse::sexp_expect::expect_string_atom;
/// Parse a label /// Parse a label
pub fn parse_label(name: Option<Sexp>) -> Result<Label, Error> { pub fn parse_label(name: Option<Sexp>) -> Result<Label, CrsnError> {
let name = expect_string_atom(name)?; let name = expect_string_atom(name)?;
Ok(Label::Named(name.trim_start_matches(':').into())) Ok(Label::Named(name.trim_start_matches(':').into()))
} }
/// Parse data disposition (address/value, without the read/write restriction) /// Parse data disposition (address/value, without the read/write restriction)
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> { pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, CrsnError> {
let tok = if let Some(tok) = tok { let tok = if let Some(tok) = tok {
tok tok
} else { } else {
return Err(Error::Parse("Expected data disposition token".into())); return Err(CrsnError::Parse("Expected data disposition token".into()));
}; };
// TODO implement masks // TODO implement masks
@ -41,7 +41,7 @@ pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
} }
} }
_ => { _ => {
Err(Error::Parse(format!("bad data disp: {:?}", tok).into())) Err(CrsnError::Parse(format!("bad data disp: {:?}", tok).into()))
} }
} }
} }

@ -1,6 +1,6 @@
use sexp::Sexp; use sexp::Sexp;
use crate::asm::error::Error; use crate::asm::error::CrsnError;
use crate::asm::instr::Instr; use crate::asm::instr::Instr;
use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::arg_parser::ArgParser;
use crate::asm::parse::parse_cond::parse_cond_branch; use crate::asm::parse::parse_cond::parse_cond_branch;
@ -10,7 +10,7 @@ use crate::module::CrsnExtension;
use super::parse_op::parse_op; use super::parse_op::parse_op;
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Instr>, Error> { pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Instr>, CrsnError> {
let mut parsed = vec![]; let mut parsed = vec![];
for expr in instrs { for expr in instrs {
let tokens = expect_list(Some(expr), false)?; let tokens = expect_list(Some(expr), false)?;

@ -1,10 +1,10 @@
use crate::asm::error::Error; use crate::asm::error::CrsnError;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::arg_parser::ArgParser;
use crate::builtin::parse::BuiltinOps; use crate::builtin::parse::BuiltinOps;
use crate::module::{CrsnExtension, ParseOpRes}; use crate::module::{CrsnExtension, ParseOpRes};
pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, Error> { pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, CrsnError> {
// Include built-in instructions // Include built-in instructions
let builtins = [BuiltinOps::new()]; let builtins = [BuiltinOps::new()];
@ -23,5 +23,5 @@ pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn Crs
} }
} }
return Err(Error::Parse(format!("Unknown instruction: {}", keyword).into())); return Err(CrsnError::Parse(format!("Unknown instruction: {}", keyword).into()));
} }

@ -1,14 +1,14 @@
use sexp::Sexp; use sexp::Sexp;
use crate::asm::data::literal::RoutineName; use crate::asm::data::literal::RoutineName;
use crate::asm::error::Error; use crate::asm::error::CrsnError;
use crate::asm::instr::Routine; use crate::asm::instr::Routine;
use crate::asm::parse::parse_instr::parse_instructions; use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom}; use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove; use crate::asm::patches::TryRemove;
use crate::module::CrsnExtension; use crate::module::CrsnExtension;
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Routine>, Error> { pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Routine>, CrsnError> {
let mut parsed = vec![]; let mut parsed = vec![];
for rt in routines { for rt in routines {
let mut def = expect_list(Some(rt), false)?; let mut def = expect_list(Some(rt), false)?;

@ -1,16 +1,16 @@
use sexp::{Atom, Sexp}; use sexp::{Atom, Sexp};
use crate::asm::error::Error; use crate::asm::error::CrsnError;
pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, Error> { pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, CrsnError> {
if let Some(expr) = expr { if let Some(expr) = expr {
match &expr { match &expr {
Sexp::Atom(_) => { Sexp::Atom(_) => {
return Err(Error::ParseIn("Expected a list".into(), expr)); return Err(CrsnError::ParseIn("Expected a list".into(), expr));
} }
Sexp::List(list) => { Sexp::List(list) => {
if !allow_empty && list.is_empty() { 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 { if let Sexp::List(list) = expr {
@ -22,10 +22,10 @@ pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, 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<Sexp>) -> Result<Atom, Error> { pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, CrsnError> {
if let Some(expr) = expr { if let Some(expr) = expr {
match &expr { match &expr {
Sexp::Atom(_atom) => { Sexp::Atom(_atom) => {
@ -36,18 +36,18 @@ pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, Error> {
} }
} }
Sexp::List(_) => { 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<Sexp>) -> Result<String, Error> { pub fn expect_string_atom(expr: Option<Sexp>) -> Result<String, CrsnError> {
match expect_atom(expr) { match expect_atom(expr) {
Ok(Atom::S(s)) => Ok(s), 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), Err(e) => Err(e),
} }
} }

@ -1,7 +1,7 @@
use sexp::{Atom, Sexp}; use sexp::{Atom, Sexp};
use crate::asm::data::literal::{Label, RoutineName}; 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::cond::parse_cond;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::arg_parser::ArgParser;
@ -28,7 +28,7 @@ impl CrsnExtension for BuiltinOps {
"builtin" "builtin"
} }
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, Error> { fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword { Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
"nop" => { "nop" => {
BuiltinOp::Nop BuiltinOp::Nop

@ -4,7 +4,7 @@ pub use eval_res::EvalRes;
use crate::asm::data::literal::Value; use crate::asm::data::literal::Value;
use crate::asm::data::Mask; use crate::asm::data::Mask;
use crate::asm::error::Error; use crate::asm::error::CrsnError;
use crate::asm::instr::Op; use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser; use crate::asm::parse::arg_parser::ArgParser;
use crate::runtime::fault::Fault; use crate::runtime::fault::Fault;
@ -23,7 +23,7 @@ pub enum ParseOpRes<T> {
impl ParseOpRes<Op> { impl ParseOpRes<Op> {
/// Helper to construct an extension op /// 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))) 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. /// the argument list and either return Ok or Err.
/// ///
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list. /// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes<Op>, Error>; fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes<Op>, CrsnError>;
/// Drop an object referenced by a handle /// Drop an object referenced by a handle
fn drop_obj(&self, fn drop_obj(&self,

@ -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 defs;
mod parse; mod parse;
mod exec; mod exec;
#[derive(Debug, Clone)]
pub struct ArithOps;
impl ArithOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for ArithOps {
fn name(&self) -> &'static str {
"arith"
}
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
parse::parse(keyword, args)
}
}

@ -1,455 +1,437 @@
use crsn::asm::data::{Rd, Wr}; use crsn::asm::data::{Rd, Wr};
use crsn::asm::error::Error; use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op; use crsn::asm::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser; use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{CrsnExtension, ParseOpRes}; use crsn::module::{ParseOpRes};
use crate::defs::ArithOp; use crate::defs::ArithOp;
#[derive(Debug, Clone)] pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
pub struct ArithOps { Ok(ParseOpRes::ext(match keyword {
_internal: () "cmp" => {
} ArithOp::Compare {
a: args.next_rd()?,
impl ArithOps { b: args.next_rd()?,
pub fn new() -> Box<dyn CrsnExtension> { }
Box::new(Self { }
_internal: ()
})
}
}
impl CrsnExtension for ArithOps { "tst" => {
fn name(&self) -> &'static str { let arg = args.next_rd()?;
"arith" ArithOp::Test { a: arg }
} }
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, Error> { "inc" => {
Ok(ParseOpRes::parsed(match keyword { let dst = args.next_wr()?;
"cmp" => { ArithOp::Add {
ArithOp::Compare { dst,
a: args.next_rd()?, a: dst.as_rd(),
b: args.next_rd()?, b: Rd::immediate(1),
}
} }
}
"tst" => { "dec" => {
let arg = args.next_rd()?; let dst = args.next_wr()?;
ArithOp::Test { a: arg } ArithOp::Sub {
dst,
a: dst.as_rd(),
b: Rd::immediate(1),
} }
}
"inc" => { "add" => {
let dst = args.next_wr()?; match args.len() {
ArithOp::Add { 3 => {
dst, ArithOp::Add {
a: dst.as_rd(), dst: args.next_wr()?,
b: Rd::immediate(1), a: args.next_rd()?,
b: args.next_rd()?,
}
} }
} 2 => {
let dst = args.next_wr()?;
"dec" => { ArithOp::Add {
let dst = args.next_wr()?; dst,
ArithOp::Sub { a: dst.as_rd(),
dst, b: args.next_rd()?,
a: dst.as_rd(), }
b: Rd::immediate(1), }
_ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into()));
} }
} }
}
"add" => { "sub" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Add { ArithOp::Sub {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
b: args.next_rd()?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
ArithOp::Add { ArithOp::Sub {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: args.next_rd()?, b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Add requires 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into()));
}
} }
}
"sub" => { "mul" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Sub { ArithOp::Mul {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
b: args.next_rd()?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
ArithOp::Sub { ArithOp::Mul {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
b: args.next_rd()?, b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Sub requires 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into()));
}
} }
}
"mul" => { "divr" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Mul { let dst = args.next_wr()?;
dst: args.next_wr()?, let rem = args.next_wr()?;
a: args.next_rd()?, let div = args.next_rd()?;
b: args.next_rd()?, ArithOp::Div {
} dst,
} rem,
2 => { a: dst.as_rd(),
let dst = args.next_wr()?; div,
ArithOp::Mul {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Mul requires 2 or 3 arguments".into()));
} }
} }
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" => { "div" => {
match args.len() { match args.len() {
3 => { 3 => {
let dst = args.next_wr()?; ArithOp::Div {
let rem = args.next_wr()?; dst: args.next_wr()?,
let div = args.next_rd()?; rem: Wr::discard(),
ArithOp::Div { a: args.next_rd()?,
dst, div: args.next_rd()?,
rem, }
a: dst.as_rd(), }
div, 2 => {
} let dst = args.next_wr()?;
} let div = args.next_rd()?;
4 => { ArithOp::Div {
ArithOp::Div { dst,
dst: args.next_wr()?, rem: Wr::discard(),
rem: args.next_wr()?, a: dst.as_rd(),
a: args.next_rd()?, div,
div: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("DivR requires 3 or 4 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into()));
}
} }
}
"div" => { "mod" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Div { ArithOp::Mod {
dst: args.next_wr()?, dst: args.next_wr()?,
rem: Wr::discard(), a: args.next_rd()?,
a: args.next_rd()?, div: args.next_rd()?,
div: args.next_rd()?, }
} }
} 2 => {
2 => { let dst = args.next_wr()?;
let dst = args.next_wr()?; let div = args.next_rd()?;
let div = args.next_rd()?; ArithOp::Mod {
ArithOp::Div { dst,
dst, a: dst.as_rd(),
rem: Wr::discard(), div,
a: dst.as_rd(),
div,
}
}
_ => {
return Err(Error::Parse("Div requires 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into()));
}
} }
}
"mod" => { "and" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Mod { ArithOp::And {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
div: args.next_rd()?, b: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
let div = args.next_rd()?; ArithOp::And {
ArithOp::Mod { dst,
dst, a: dst.as_rd(),
a: dst.as_rd(), b: args.next_rd()?,
div,
}
}
_ => {
return Err(Error::Parse("Mod requires 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into()));
}
} }
}
"and" => { "or" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::And { ArithOp::Or {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
b: 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()));
} }
} }
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" => { "xor" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Or { ArithOp::Xor {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
b: 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()));
} }
} }
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" => { "cpl" => {
match args.len() { match args.len() {
3 => { 2 => {
ArithOp::Xor { ArithOp::Cpl {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
b: args.next_rd()?, }
} }
} 1 => {
2 => { let dst = args.next_wr()?;
let dst = args.next_wr()?; ArithOp::Cpl {
ArithOp::Xor { dst,
dst, a: dst.as_rd(),
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Xor requires 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into()));
}
} }
}
"cpl" => { "rol" => {
match args.len() { match args.len() {
2 => { 3 => {
ArithOp::Cpl { ArithOp::Rol {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
} n: args.next_rd()?,
} }
1 => { }
let dst = args.next_wr()?; 2 => {
ArithOp::Cpl { let dst = args.next_wr()?;
dst, ArithOp::Rol {
a: dst.as_rd(), 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" => { "ror" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Rol { ArithOp::Ror {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
n: 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()));
} }
} }
} 2 => {
let dst = args.next_wr()?;
"ror" => { ArithOp::Ror {
match args.len() { dst,
3 => { a: dst.as_rd(),
ArithOp::Ror { n: args.next_rd()?,
dst: args.next_wr()?, }
a: args.next_rd()?, }
n: args.next_rd()?, 1 => {
} let dst = args.next_wr()?;
} ArithOp::Ror {
2 => { dst,
let dst = args.next_wr()?; a: dst.as_rd(),
ArithOp::Ror { n: Rd::immediate(1),
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()));
} }
} }
_ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into()));
}
} }
}
"lsl" | "asl" => { "lsl" | "asl" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Lsl { ArithOp::Lsl {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
n: args.next_rd()?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
ArithOp::Lsl { ArithOp::Lsl {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: args.next_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()));
} }
} }
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" => { "lsr" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Lsr { ArithOp::Lsr {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
n: args.next_rd()?, n: args.next_rd()?,
} }
} }
2 => { 2 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
ArithOp::Lsr { ArithOp::Lsr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: args.next_rd()?, n: args.next_rd()?,
} }
} }
1 => { 1 => {
let dst = args.next_wr()?; let dst = args.next_wr()?;
ArithOp::Lsr { ArithOp::Lsr {
dst, dst,
a: dst.as_rd(), a: dst.as_rd(),
n: Rd::immediate(1), n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Lsr requires 1, 2 or 3 arguments".into()));
} }
} }
_ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into()));
}
} }
}
"asr" => { "asr" => {
match args.len() { match args.len() {
3 => { 3 => {
ArithOp::Asr { ArithOp::Asr {
dst: args.next_wr()?, dst: args.next_wr()?,
a: args.next_rd()?, a: args.next_rd()?,
n: 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()));
} }
} }
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 => { _other => {
return Ok(ParseOpRes::Unknown(args)); return Ok(ParseOpRes::Unknown(args));
} }
})) }))
}
} }

@ -67,7 +67,7 @@ impl OpTrait for StackOp {
// //
} }
pub(crate) fn drop_stack(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> { pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> {
let stacks: &mut Stacks = state.ext_mut(); let stacks: &mut Stacks = state.ext_mut();
Ok(stacks.store.remove(&handle).map(|_| ())) Ok(stacks.store.remove(&handle).map(|_| ()))
} }

@ -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 defs;
mod parse; mod parse;
mod exec; mod exec;
#[derive(Debug, Clone)]
pub struct StackOps;
impl StackOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for StackOps {
fn name(&self) -> &'static str {
"stacks"
}
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
parse::parse(keyword, args)
}
}

@ -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::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser; use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{CrsnExtension, ParseOpRes}; use crsn::module::{ParseOpRes};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{RunState, ThreadInfo};
use crate::defs::StackOp;
#[derive(Debug, Clone)]
pub struct StackOps {
_internal: ()
}
impl StackOps { use crate::defs::StackOp;
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self {
_internal: ()
})
}
}
impl CrsnExtension for StackOps {
fn name(&self) -> &'static str {
"stacks"
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, Error> {
Ok(ParseOpRes::parsed(match keyword {
"stack" => {
StackOp::NewStack {
dst: args.next_wr()?,
}
}
"push" => { pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
StackOp::Push { Ok(ParseOpRes::ext(match keyword {
obj: args.next_rdobj()?, "stack" => {
src: args.next_rd()?, StackOp::NewStack {
} dst: args.next_wr()?,
} }
}
"pop" => { "push" => {
StackOp::Pop { StackOp::Push {
dst: args.next_wr()?, obj: args.next_rdobj()?,
obj: args.next_rdobj()?, src: args.next_rd()?,
}
} }
}
_other => { "pop" => {
return Ok(ParseOpRes::Unknown(args)); StackOp::Pop {
dst: args.next_wr()?,
obj: args.next_rdobj()?,
} }
})) }
}
fn drop_obj(&self, _ti: &ThreadInfo, state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> _other => {
{ return Ok(ParseOpRes::Unknown(args));
crate::exec::drop_stack(state, handle) }
} }))
} }

Loading…
Cancel
Save