pull/21/head
Ondřej Hruška 4 years ago
parent fe8bf87e6d
commit 6eef2b7ae3
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      crsn/src/asm/instr/flatten.rs
  2. 2
      crsn/src/asm/parse/parse_op.rs
  3. 8
      crsn/src/builtin/exec.rs
  4. 24
      crsn/src/builtin/mod.rs
  5. 315
      crsn/src/builtin/parse.rs
  6. 4
      crsn/src/module/mod.rs

@ -1,5 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicU32, Ordering}; 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};

@ -2,8 +2,8 @@ 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::TokenParser; use crate::asm::parse::arg_parser::TokenParser;
use crate::builtin::parse::BuiltinOps;
use crate::module::ParseRes; use crate::module::ParseRes;
use crate::builtin::BuiltinOps;
pub fn parse_op<'a>(mut keyword: &str, mut arg_tokens: TokenParser<'a>) -> Result<Option<Op>, CrsnError> { pub fn parse_op<'a>(mut keyword: &str, mut arg_tokens: TokenParser<'a>) -> Result<Option<Op>, CrsnError> {
// Include built-in instructions // Include built-in instructions

@ -9,10 +9,10 @@ use crate::runtime::fault::Fault;
use crate::runtime::frame::StackFrame; use crate::runtime::frame::StackFrame;
use crate::runtime::run_thread::{state::RunState, ThreadInfo}; use crate::runtime::run_thread::{state::RunState, ThreadInfo};
use sexp::Sexp; use sexp::Sexp;
use sexp::Atom;
use std::str::FromStr;
use std::fmt::Display;
use crate::utils::A;
impl OpTrait for BuiltinOp { impl OpTrait for BuiltinOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> { fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {

@ -1,3 +1,27 @@
use crate::module::{CrsnExtension, ParseRes};
use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::instr::op::OpKind;
use crate::asm::error::CrsnError;
pub mod defs; pub mod defs;
pub mod exec; pub mod exec;
pub mod parse; pub mod parse;
#[derive(Debug, Clone)]
pub struct BuiltinOps;
impl BuiltinOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for BuiltinOps {
fn name(&self) -> &'static str {
"builtin"
}
fn parse_op<'a>(&self, keyword: &str, args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
parse::parse_op(keyword, args)
}
}

@ -5,224 +5,205 @@ use crate::asm::data::reg::parse_reg;
use crate::asm::error::CrsnError; use crate::asm::error::CrsnError;
use crate::asm::instr::op::OpKind; use crate::asm::instr::op::OpKind;
use crate::asm::parse::arg_parser::TokenParser; use crate::asm::parse::arg_parser::TokenParser;
use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_rd, parse_reg_alias, parse_value, parse_u64, parse_label_str}; use crate::asm::parse::parse_data::{parse_constant_name, parse_label, parse_rd, parse_reg_alias, parse_value, parse_label_str};
use crate::asm::parse::sexp_expect::expect_string_atom; use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::builtin::defs::{Barrier, BuiltinOp}; use crate::builtin::defs::{Barrier, BuiltinOp};
use crate::module::{CrsnExtension, ParseRes}; use crate::module::{CrsnExtension, ParseRes};
use crate::utils::A; use crate::utils::A;
use std::convert::TryFrom;
#[derive(Debug, Clone)]
pub struct BuiltinOps {
_internal: ()
}
impl BuiltinOps { pub(crate) fn parse_op<'a>(keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
pub fn new() -> Box<dyn CrsnExtension> { let pcx = args.pcx;
Box::new(Self {
_internal: ()
})
}
}
impl CrsnExtension for BuiltinOps { Ok(ParseRes::Parsed(OpKind::BuiltIn(match keyword {
fn name(&self) -> &'static str { "nop" => {
"builtin" BuiltinOp::Nop
} }
fn parse_op<'a>(&self, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> { "halt" => {
let pcx = args.pcx; BuiltinOp::Halt
}
Ok(ParseRes::Parsed(OpKind::BuiltIn(match keyword { "sleep" => {
"nop" => { BuiltinOp::Sleep {
BuiltinOp::Nop micros: args.next_rd()?,
} }
}
"halt" => { "sym" => {
BuiltinOp::Halt let alias = parse_reg_alias(args.next())?;
} trace!("alias={:?}", alias);
let register = parse_reg(&args.next_string()?)?;
trace!("register={:?}", alias);
"sleep" => { let mut pstate = pcx.state.borrow_mut();
BuiltinOp::Sleep { if pstate.reg_aliases.contains_key(&alias) {
micros: args.next_rd()?, return Err(CrsnError::Parse(format!("Register alias \"{}\" already defined!", alias).into()));
}
} }
"sym" => { if pstate.constants.contains_key(&alias) {
let alias = parse_reg_alias(args.next())?; return Err(CrsnError::Parse(format!("Name \"{}\" already used for a constant!", alias).into()));
trace!("alias={:?}", alias); }
let register = parse_reg(&args.next_string()?)?;
trace!("register={:?}", alias);
let mut pstate = pcx.state.borrow_mut(); if pstate.reg_aliases.iter().find(|x| x.1 == &register).is_some() {
if pstate.reg_aliases.contains_key(&alias) { return Err(CrsnError::Parse(format!("Register \"{}\" already aliased!", register).into()));
return Err(CrsnError::Parse(format!("Register alias \"{}\" already defined!", alias).into())); }
}
if pstate.constants.contains_key(&alias) { pstate.reg_aliases.insert(alias, register);
return Err(CrsnError::Parse(format!("Name \"{}\" already used for a constant!", alias).into()));
}
if pstate.reg_aliases.iter().find(|x| x.1 == &register).is_some() { return Ok(ParseRes::ParsedNone);
return Err(CrsnError::Parse(format!("Register \"{}\" already aliased!", register).into())); }
}
pstate.reg_aliases.insert(alias, register); "unsym" => {
let alias = parse_reg_alias(args.next())?;
return Ok(ParseRes::ParsedNone); let mut pstate = pcx.state.borrow_mut();
if pstate.reg_aliases.remove(&alias).is_none() {
return Err(CrsnError::Parse(format!("Register alias \"{}\" not defined!", alias).into()));
} }
return Ok(ParseRes::ParsedNone);
}
"unsym" => { "def" => {
let alias = parse_reg_alias(args.next())?; let name = parse_constant_name(args.next())?;
let value = parse_value(args.next(), pcx)?;
let mut pstate = pcx.state.borrow_mut(); let mut pstate = pcx.state.borrow_mut();
if pstate.reg_aliases.remove(&alias).is_none() { if pstate.constants.contains_key(&name) {
return Err(CrsnError::Parse(format!("Register alias \"{}\" not defined!", alias).into())); return Err(CrsnError::Parse(format!("Constant \"{}\" already defined!", name).into()));
}
return Ok(ParseRes::ParsedNone);
} }
"def" => { if pstate.reg_aliases.contains_key(&name) {
let name = parse_constant_name(args.next())?; return Err(CrsnError::Parse(format!("Name \"{}\" already used for a register alias!", name).into()));
let value = parse_value(args.next(), pcx)?; }
let mut pstate = pcx.state.borrow_mut();
if pstate.constants.contains_key(&name) {
return Err(CrsnError::Parse(format!("Constant \"{}\" already defined!", name).into()));
}
if pstate.reg_aliases.contains_key(&name) {
return Err(CrsnError::Parse(format!("Name \"{}\" already used for a register alias!", name).into()));
}
pstate.constants.insert(name, value); pstate.constants.insert(name, value);
return Ok(ParseRes::ParsedNone); return Ok(ParseRes::ParsedNone);
} }
"undef" => { "undef" => {
let name = parse_constant_name(args.next())?; let name = parse_constant_name(args.next())?;
let mut pstate = pcx.state.borrow_mut(); let mut pstate = pcx.state.borrow_mut();
if pstate.constants.remove(&name).is_none() { if pstate.constants.remove(&name).is_none() {
return Err(CrsnError::Parse(format!("Constant \"{}\" not defined!", name).into())); return Err(CrsnError::Parse(format!("Constant \"{}\" not defined!", name).into()));
}
return Ok(ParseRes::ParsedNone);
} }
return Ok(ParseRes::ParsedNone);
}
"j" => { "j" => {
let dest = parse_label(args.next())?; let dest = parse_label(args.next())?;
BuiltinOp::Jump(dest) BuiltinOp::Jump(dest)
} }
"fj" => { "fj" => {
let dest = parse_label(args.next())?; let dest = parse_label(args.next())?;
BuiltinOp::FarJump(dest) BuiltinOp::FarJump(dest)
} }
"call" => { "call" => {
let dest = RoutineName { name: args.next_string()?, arity: args.len() as u8 }; let dest = RoutineName { name: args.next_string()?, arity: args.len() as u8 };
let mut call_args = vec![]; let mut call_args = vec![];
for t in args { for t in args {
call_args.push(parse_rd(Some(t), pcx)?); call_args.push(parse_rd(Some(t), pcx)?);
}
BuiltinOp::Call(dest, call_args)
} }
BuiltinOp::Call(dest, call_args)
}
"ret" => { "ret" => {
let mut ret_vals = vec![]; let mut ret_vals = vec![];
for t in args { for t in args {
ret_vals.push(parse_rd(Some(t), pcx)?); ret_vals.push(parse_rd(Some(t), pcx)?);
}
BuiltinOp::Ret(ret_vals)
} }
BuiltinOp::Ret(ret_vals)
}
"routine" => { "routine" => {
let name = args.next_string()?; let name = args.next_string()?;
BuiltinOp::Routine(parse_routine_name(name)?) BuiltinOp::Routine(parse_routine_name(name)?)
} }
"skip" => { "skip" => {
BuiltinOp::Skip(args.next_rd()?) BuiltinOp::Skip(args.next_rd()?)
} }
"barrier" => { "barrier" => {
BuiltinOp::Barrier { BuiltinOp::Barrier {
kind: Barrier::Standalone, kind: Barrier::Standalone,
msg: match args.next() { msg: match args.next() {
None => None, None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()), Some(s) => Some(expect_string_atom(Some(s))?.into()),
}, },
}
} }
}
"barrier-open" => { "barrier-open" => {
BuiltinOp::Barrier { BuiltinOp::Barrier {
kind: Barrier::Open(parse_label(args.next())?), kind: Barrier::Open(parse_label(args.next())?),
msg: None, msg: None,
}
} }
}
"barrier-close" => { "barrier-close" => {
BuiltinOp::Barrier { BuiltinOp::Barrier {
kind: Barrier::Close(parse_label(args.next())?), kind: Barrier::Close(parse_label(args.next())?),
msg: None, msg: None,
}
} }
}
"fault" => { "fault" => {
BuiltinOp::Fault(match args.next() { BuiltinOp::Fault(match args.next() {
None => None, None => None,
Some(s) => Some(expect_string_atom(Some(s))?.into()), Some(s) => Some(expect_string_atom(Some(s))?.into()),
}) })
} }
"ld" => { "ld" => {
BuiltinOp::Move { BuiltinOp::Move {
dst: args.next_wr()?, dst: args.next_wr()?,
src: args.next_rd()?, src: args.next_rd()?,
}
} }
}
"sst" => { "sst" => {
BuiltinOp::StoreStatus { BuiltinOp::StoreStatus {
dst: args.next_wr()?, dst: args.next_wr()?,
}
} }
}
"sld" => { "sld" => {
BuiltinOp::LoadStatus { BuiltinOp::LoadStatus {
src: args.next_rd()?, src: args.next_rd()?,
}
} }
}
"drop" => { "drop" => {
BuiltinOp::Drop(args.next_rdobj()?) BuiltinOp::Drop(args.next_rdobj()?)
} }
"far" => { "far" => {
if let Some(Sexp::Atom(Atom::S(ref label))) = args.peek() { if let Some(Sexp::Atom(Atom::S(ref label))) = args.peek() {
if let Some(label) = label.strip_prefix(':') { if let Some(label) = label.strip_prefix(':') {
let label = Label::Named(label.to_string()); let label = Label::Named(label.to_string());
BuiltinOp::FarLabel(label) BuiltinOp::FarLabel(label)
} else {
return Ok(ParseRes::Unknown(args));
}
} else { } else {
return Ok(ParseRes::Unknown(args)); return Ok(ParseRes::Unknown(args));
} }
} else {
return Ok(ParseRes::Unknown(args));
} }
}
other => { other => {
if let Some(label) = other.strip_prefix(':') { if let Some(label) = other.strip_prefix(':') {
BuiltinOp::Label(parse_label_str(label)?) BuiltinOp::Label(parse_label_str(label)?)
} else { } else {
return Ok(ParseRes::Unknown(args)); return Ok(ParseRes::Unknown(args));
}
} }
}))) }
} })))
} }
pub(crate) fn parse_routine_name(name: String) -> Result<RoutineName, CrsnError> { pub(crate) fn parse_routine_name(name: String) -> Result<RoutineName, CrsnError> {
@ -304,16 +285,16 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::any::Any;
use std::cell::RefCell;
use std::sync::atomic::AtomicU32; use std::sync::atomic::AtomicU32;
use crate::asm::instr::{Flatten, InstrWithBranches}; use crate::asm::instr::{Flatten};
use crate::asm::parse::{parse_instructions, ParserContext}; use crate::asm::parse::{parse_instructions, ParserContext};
use crate::asm::parse::sexp_expect::expect_list; use crate::asm::parse::sexp_expect::expect_list;
use crate::builtin::defs::BuiltinOp;
use crate::builtin::parse::BuiltinOps;
use crate::module::OpTrait; use crate::module::OpTrait;
use crate::builtin::BuiltinOps;
#[test] #[test]
fn roundtrip() { fn roundtrip() {
@ -374,7 +355,7 @@ mod test {
let parsers = &[parser]; let parsers = &[parser];
for (sample, expected) in samples { for (sample, expected) in samples {
let mut pcx = ParserContext { let pcx = ParserContext {
parsers, parsers,
state: Default::default(), state: Default::default(),
}; };
@ -386,7 +367,7 @@ mod test {
.expect("parse sexp"); .expect("parse sexp");
let list = expect_list(Some(s), false).unwrap(); let list = expect_list(Some(s), false).unwrap();
let num = AtomicU32::new(0); let num = AtomicU32::new(0);
let mut parsed = parse_instructions(list.into_iter(), &pcx) let parsed = parse_instructions(list.into_iter(), &pcx)
.expect("parse instr").flatten(&num) .expect("parse instr").flatten(&num)
.expect("flatten").remove(0); .expect("flatten").remove(0);
@ -402,7 +383,7 @@ mod test {
.expect("parse sexp (2c)"); .expect("parse sexp (2c)");
let list = expect_list(Some(s), false).unwrap(); let list = expect_list(Some(s), false).unwrap();
let num = AtomicU32::new(0); let num = AtomicU32::new(0);
let mut parsed = parse_instructions(list.into_iter(), &pcx) let parsed = parse_instructions(list.into_iter(), &pcx)
.expect("parse instr (2c)").flatten(&num) .expect("parse instr (2c)").flatten(&num)
.expect("flatten (2c)").remove(0); .expect("flatten (2c)").remove(0);

@ -1,6 +1,6 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug};
pub use eval_res::EvalRes; pub use eval_res::EvalRes;
@ -14,7 +14,7 @@ use crate::runtime::fault::Fault;
use crate::runtime::run_thread::state::RunState; use crate::runtime::run_thread::state::RunState;
use crate::runtime::run_thread::ThreadInfo; use crate::runtime::run_thread::ThreadInfo;
use sexp::Sexp; use sexp::Sexp;
use std::fmt;
mod eval_res; mod eval_res;

Loading…
Cancel
Save