forked from MightyPork/crsn
AMAZING NEW FEATURES ldn, bfio
This commit is contained in:
@@ -2,9 +2,10 @@ use sexp::{Sexp, SourcePosition};
|
||||
|
||||
use crate::asm::data::{Rd, RdData, RdObj, Wr, RdWr};
|
||||
use crate::asm::error::CrsnError;
|
||||
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
|
||||
use crate::asm::parse::parse_data::{parse_rd, parse_wr, parse_value};
|
||||
use crate::asm::parse::ParserContext;
|
||||
use crate::asm::parse::sexp_expect::expect_string_atom;
|
||||
use crate::asm::data::literal::Value;
|
||||
|
||||
/// Utility for argument parsing
|
||||
#[derive(Debug)]
|
||||
@@ -85,6 +86,12 @@ impl<'a> TokenParser<'a> {
|
||||
Ok(esa)
|
||||
}
|
||||
|
||||
/// Get the next value entry
|
||||
pub fn next_value(&mut self) -> Result<(Value, SourcePosition), CrsnError> {
|
||||
let next = self.next_or_err()?;
|
||||
parse_value(next, self.pcx)
|
||||
}
|
||||
|
||||
/// Get the next entry as read location
|
||||
pub fn next_rd(&mut self) -> Result<Rd, CrsnError> {
|
||||
let next = self.next_or_err()?;
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::asm::patches::ErrWithPos;
|
||||
|
||||
fn is_valid_identifier(name: &str) -> bool {
|
||||
// ascii symbols "!\"#$_&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||
const BLACKLIST : &str = "!\"#$&'()*+,-./:;<=>?@[\\]^`{|}~";
|
||||
const BLACKLIST : &str = "!\"#$&'()*+,./;<=>?@[\\]^`{|}~";
|
||||
name != "_"
|
||||
&& !name.starts_with(|c: char| c.is_ascii_digit() || BLACKLIST.contains(c))
|
||||
&& !name.contains(|c : char| c.is_whitespace() || BLACKLIST.contains(c))
|
||||
@@ -161,27 +161,34 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
|
||||
}
|
||||
|
||||
/// Parse immediate value
|
||||
pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<Value, CrsnError> {
|
||||
pub fn parse_value(tok: Sexp, pcx: &ParserContext) -> Result<(Value, SourcePosition), CrsnError> {
|
||||
match tok {
|
||||
Sexp::Atom(Atom::I(val), _pos) => {
|
||||
Ok(unsafe { std::mem::transmute(val) })
|
||||
Sexp::Atom(Atom::I(val), pos) => {
|
||||
Ok((unsafe { std::mem::transmute(val) }, pos))
|
||||
}
|
||||
Sexp::Atom(Atom::U(val), _pos) => {
|
||||
Ok(val)
|
||||
Sexp::Atom(Atom::U(val), pos) => {
|
||||
Ok((val, pos))
|
||||
}
|
||||
Sexp::Atom(Atom::C(val), _pos) => {
|
||||
Ok(val as u64)
|
||||
Sexp::Atom(Atom::C(val), pos) => {
|
||||
Ok((val as u64, pos))
|
||||
}
|
||||
Sexp::Atom(Atom::QS(_), pos) => {
|
||||
Err(CrsnError::Parse("quoted string not expected here".into(), pos))
|
||||
}
|
||||
Sexp::Atom(Atom::F(val), _) => {
|
||||
Ok(unsafe { std::mem::transmute(val) })
|
||||
Sexp::Atom(Atom::F(val), pos) => {
|
||||
Ok((unsafe { std::mem::transmute(val) }, pos))
|
||||
}
|
||||
Sexp::Atom(Atom::S(s), pos) => {
|
||||
let pstate = pcx.state.borrow();
|
||||
if let Some(val) = pstate.constants.get(&s) {
|
||||
return Ok(*val);
|
||||
return Ok((*val, pos));
|
||||
}
|
||||
|
||||
/* extension constants */
|
||||
for p in pcx.parsers {
|
||||
if let Some(val) = p.get_constant_value(&s) {
|
||||
return Ok((val, pos));
|
||||
}
|
||||
}
|
||||
|
||||
Err(CrsnError::Parse(format!("unknown constant: {}", s).into(), pos))
|
||||
|
||||
@@ -70,8 +70,10 @@ pub enum BuiltinOp {
|
||||
/// Deallocate an extension object.
|
||||
/// The object is released and the handle becomes invalid.
|
||||
Delete(RdObj),
|
||||
/// Copy value
|
||||
/// Move a value
|
||||
MoveValue { dst: Wr, src: Rd },
|
||||
/// Move N values
|
||||
MoveMultipleValues { dst: Wr, src: Rd, count: Rd },
|
||||
/// Swap two registers
|
||||
SwapValues { a: RdWr, b: RdWr },
|
||||
/// Store runtime status to a register
|
||||
|
||||
@@ -109,6 +109,17 @@ impl OpTrait for BuiltinOp {
|
||||
state.update_status(val);
|
||||
state.write(dst, val)?;
|
||||
}
|
||||
BuiltinOp::MoveMultipleValues { dst, src, count } => {
|
||||
state.clear_status();
|
||||
let mut count = state.read(count)?;
|
||||
let mut last = 0;
|
||||
while count > 0 {
|
||||
last = state.read(src)?;
|
||||
state.write(dst, last)?;
|
||||
count -= 1;
|
||||
}
|
||||
state.update_status(last);
|
||||
}
|
||||
BuiltinOp::SwapValues { a, b } => {
|
||||
let aa = state.read(a)?;
|
||||
let bb = state.read(b)?;
|
||||
|
||||
@@ -88,7 +88,7 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
|
||||
|
||||
"def" => {
|
||||
let (name, namepos) = parse_constant_name(args.next_or_err()?)?;
|
||||
let value = parse_value(args.next_or_err()?, pcx)?;
|
||||
let (value, _valuepos) = parse_value(args.next_or_err()?, pcx)?;
|
||||
|
||||
let mut pstate = pcx.state.borrow_mut();
|
||||
if pstate.constants.contains_key(&name) {
|
||||
@@ -189,6 +189,14 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
|
||||
}
|
||||
}
|
||||
|
||||
"ldn" => {
|
||||
BuiltinOp::MoveMultipleValues {
|
||||
dst: args.next_wr()?,
|
||||
src: args.next_rd()?,
|
||||
count: args.next_rd()?,
|
||||
}
|
||||
}
|
||||
|
||||
"swap" => {
|
||||
BuiltinOp::SwapValues {
|
||||
a: args.next_rdwr()?,
|
||||
@@ -309,7 +317,8 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
|
||||
}
|
||||
BuiltinOp::Delete(obj) => sexp::list(&[A("del"), A(obj)]),
|
||||
BuiltinOp::MoveValue { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]),
|
||||
BuiltinOp::SwapValues { a, b } => sexp::list(&[A("swp"), A(a), A(b)]),
|
||||
BuiltinOp::MoveMultipleValues { dst, src, count } => sexp::list(&[A("ldn"), A(dst), A(src), A(count)]),
|
||||
BuiltinOp::SwapValues { a, b } => sexp::list(&[A("swap"), A(a), A(b)]),
|
||||
BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
|
||||
BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)])
|
||||
}
|
||||
@@ -382,6 +391,7 @@ mod test {
|
||||
("(ld r0 r0)", "(ld r0 r0)"),
|
||||
("(ld r0 156)", "(ld r0 156)"),
|
||||
("(ld _ -32767)", "(ld _ -32767)"),
|
||||
("(ldn _ @r0 7)", "(ldn _ @r0 7)"),
|
||||
("(stf r0)", "(stf r0)"),
|
||||
("(ldf r0)", "(ldf r0)"),
|
||||
("(far :label)", "(far :label)"),
|
||||
|
||||
Reference in New Issue
Block a user