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 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<Register> {
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()))?
}
}

@ -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<sexp::Error>),
#[error("Parse error: {0:?}")]

@ -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<Cond, Error> {
pub fn parse_cond(text: &str) -> Result<Cond, CrsnError> {
Ok(match text.trim_end_matches('?') {
"eq" | "=" | "==" => Cond::Equal,
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
@ -66,7 +66,7 @@ pub fn parse_cond(text: &str) -> Result<Cond, Error> {
"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()));
}
})
}

@ -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<Vec<Op>, Error>;
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
}
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];
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<Vec<Op>, Error> {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, 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<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();
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<Op>) -> Result<Vec<Op>, 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<Op>) -> Result<Vec<Op>, 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 => {

@ -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<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)?;
trace!("--- Compiled program ---");

@ -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<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 subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;

@ -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<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 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)?))

@ -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<Sexp>) -> Result<Label, Error> {
pub fn parse_label(name: Option<Sexp>) -> Result<Label, CrsnError> {
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<Sexp>) -> Result<DataDisp, Error> {
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, CrsnError> {
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<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 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<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![];
for expr in instrs {
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::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<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
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 crate::asm::data::literal::RoutineName;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::Routine;
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_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![];
for rt in routines {
let mut def = expect_list(Some(rt), false)?;

@ -1,16 +1,16 @@
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 {
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<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 {
match &expr {
Sexp::Atom(_atom) => {
@ -36,18 +36,18 @@ pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, Error> {
}
}
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) {
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),
}
}

@ -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<ParseOpRes<Op>, Error> {
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
"nop" => {
BuiltinOp::Nop

@ -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<T> {
impl ParseOpRes<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)))
}
}
@ -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<ParseOpRes<Op>, Error>;
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes<Op>, CrsnError>;
/// Drop an object referenced by a handle
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 parse;
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::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<dyn CrsnExtension> {
Box::new(Self {
_internal: ()
})
}
}
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, 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<ParseOpRes<Op>, 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));
}
}))
}

@ -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();
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 parse;
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::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<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()?,
}
}
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<ParseOpRes<Op>, 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<Option<()>, Fault>
{
crate::exec::drop_stack(state, handle)
}
_other => {
return Ok(ParseOpRes::Unknown(args));
}
}))
}

Loading…
Cancel
Save