implement "lds" for objects (buffers, cin)

This commit is contained in:
2020-10-15 20:38:43 +02:00
parent 1e6e45ea72
commit 2d4f6b4af1
13 changed files with 197 additions and 40 deletions
+26 -7
View File
@@ -3,6 +3,8 @@ use std::fmt;
use crate::asm::data::{RdData, Register};
use crate::asm::data::literal::Value;
use crate::runtime::run_thread::RunState;
use crate::runtime::fault::Fault;
/// Data source argument (read-only)
#[derive(Clone, Copy, Eq, PartialEq)]
@@ -47,14 +49,25 @@ impl Debug for Rd {
/// Reference an object through a handle
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct RdObj(Register);
pub enum RdObj {
Reg(Register),
Imm(Value),
}
impl RdObj {
pub const fn new(reg: Register) -> Self {
RdObj(reg)
pub const fn from_reg(reg: Register) -> Self {
RdObj::Reg(reg)
}
pub const fn reg(self) -> Register {
self.0
pub const fn from_value(value: Value) -> Self {
RdObj::Imm(value)
}
pub fn read(self, state: &mut RunState) -> Result<Value, Fault> {
Ok(match self {
RdObj::Reg(r) => state.read(Rd::new(RdData::Register(r)))?,
RdObj::Imm(v) => v,
})
}
}
@@ -66,12 +79,18 @@ impl From<&RdObj> for RdObj {
impl Display for RdObj {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "@{}", self.0)
match self {
RdObj::Reg(r) => write!(f, "@{}", r),
RdObj::Imm(v) => write!(f, "@{:#x}", v)
}
}
}
impl Debug for RdObj {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Obj({})", self.reg())
match self {
RdObj::Reg(r) => write!(f, "Obj({})", r),
RdObj::Imm(v) => write!(f, "Obj({:#x})", v)
}
}
}
+1 -1
View File
@@ -102,7 +102,7 @@ impl<'a> TokenParser<'a> {
pub fn next_rdobj(&mut self) -> Result<RdObj, CrsnError> {
match parse_rd(self.next_or_err()?, self.pcx)? {
Rd(RdData::RegObject(reg)) => {
Ok(RdObj::new(reg))
Ok(RdObj::from_reg(reg))
}
other => {
Err(CrsnError::Parse(
+7 -6
View File
@@ -33,6 +33,7 @@ impl SleepUnit {
#[derive(Clone, Debug, PartialEq)]
pub enum LdsValue {
Values(Vec<Rd>),
Handle(RdObj),
Chars(String),
}
@@ -77,17 +78,17 @@ pub enum BuiltinOp {
/// The object is released and the handle becomes invalid.
Delete(RdObj),
/// Move a value
Move { dst: Wr, src: Rd },
Load { dst: Wr, src: Rd },
/// Move lower 32 bits
Move32 { dst: RdWr, src: Rd },
Load32 { dst: RdWr, src: Rd },
/// Move lower 16 bits
Move16 { dst: RdWr, src: Rd },
Load16 { dst: RdWr, src: Rd },
/// Move lower 8 bits
Move8 { dst: RdWr, src: Rd },
Load8 { dst: RdWr, src: Rd },
/// Move N values
MoveMultiple { dst: Wr, src: Rd, count: Rd },
LoadMultiple { dst: Wr, src: Rd, count: Rd },
/// Move values from a string or integer list
MoveSequence { dst: Wr, value: LdsValue },
LoadSequence { dst: Wr, value: LdsValue },
/// Swap two registers
Exchange { a: RdWr, b: RdWr },
/// Store runtime status to a register
+25 -11
View File
@@ -2,7 +2,6 @@ use std::time::Duration;
use sexp::Sexp;
use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::{Addr, Value};
use crate::builtin::defs::{Barrier, BuiltinOp, LdsValue};
use crate::module::{EvalRes, OpTrait};
@@ -103,13 +102,13 @@ impl OpTrait for BuiltinOp {
let pc = state.get_pc();
program.validate_jump(pc, Addr((pc.0 as i64 + res.advance) as u64))?;
}
BuiltinOp::Move { dst, src } => {
BuiltinOp::Load { dst, src } => {
state.clear_status();
let val = state.read(src)?;
state.update_status(val);
state.write(dst, val)?;
}
BuiltinOp::MoveMultiple { dst, src, count } => {
BuiltinOp::LoadMultiple { dst, src, count } => {
state.clear_status();
let mut count = state.read(count)?;
let mut last = 0;
@@ -120,7 +119,7 @@ impl OpTrait for BuiltinOp {
}
state.update_status(last);
}
BuiltinOp::Move32 { dst, src } => {
BuiltinOp::Load32 { dst, src } => {
state.clear_status();
let new = state.read(src)?;
let old = state.read(dst)?;
@@ -128,7 +127,7 @@ impl OpTrait for BuiltinOp {
state.update_status(val);
state.write(dst, val)?;
}
BuiltinOp::Move16 { dst, src } => {
BuiltinOp::Load16 { dst, src } => {
state.clear_status();
let new = state.read(src)?;
let old = state.read(dst)?;
@@ -136,7 +135,7 @@ impl OpTrait for BuiltinOp {
state.update_status(val);
state.write(dst, val)?;
}
BuiltinOp::Move8 { dst, src } => {
BuiltinOp::Load8 { dst, src } => {
state.clear_status();
let new = state.read(src)?;
let old = state.read(dst)?;
@@ -144,7 +143,7 @@ impl OpTrait for BuiltinOp {
state.update_status(val);
state.write(dst, val)?;
}
BuiltinOp::MoveSequence { dst, value } => {
BuiltinOp::LoadSequence { dst, value } => {
match value {
LdsValue::Values(vals) => {
for val in vals {
@@ -157,6 +156,21 @@ impl OpTrait for BuiltinOp {
state.write(dst, val as Value)?;
}
}
LdsValue::Handle(h) => {
let hv = h.read(state)?;
let mut found = false;
for ex in info.program.extensions.iter() {
if ex.read_obj_all(state, *dst, hv)?.is_some() {
found = true;
}
}
if !found {
warn!("Object {:#x} to read does not exist!", hv);
state.set_flag(Flag::Invalid, true);
}
}
}
}
BuiltinOp::Exchange { a, b } => {
@@ -177,17 +191,17 @@ impl OpTrait for BuiltinOp {
std::thread::sleep(Duration::from_micros(state.read(micros)? * unit_us.micros()))
}
BuiltinOp::Delete(obj) => {
let x = state.read(Rd::new(RdData::Register(obj.reg())))?;
let hv = obj.read(state)?;
trace!("Del object: {:#x}", x);
trace!("Del object: {:#x}", hv);
let mut dropped = false;
for ex in info.program.extensions.iter() {
if ex.drop_obj(info, state, x)?.is_some() {
if ex.drop_obj(info, state, hv)?.is_some() {
dropped = true;
}
}
if !dropped {
warn!("Object {:#x} to del does not exist!", x);
warn!("Object {:#x} to del does not exist!", hv);
state.set_flag(Flag::Invalid, true);
}
}
+35 -13
View File
@@ -11,6 +11,7 @@ use crate::asm::patches::ErrWithPos;
use crate::builtin::defs::{Barrier, BuiltinOp, SleepUnit, LdsValue};
use crate::module::ParseRes;
use crate::utils::A;
use crate::asm::data::{Rd, RdData, RdObj};
pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: TokenParser<'a>) -> Result<ParseRes<'a, OpKind>, CrsnError> {
let pcx = args.pcx;
@@ -183,35 +184,35 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
}
"ld" => {
BuiltinOp::Move {
BuiltinOp::Load {
dst: args.next_wr()?,
src: args.next_rd()?,
}
}
"ld32" => {
BuiltinOp::Move32 {
BuiltinOp::Load32 {
dst: args.next_rdwr()?,
src: args.next_rd()?,
}
}
"ld16" => {
BuiltinOp::Move16 {
BuiltinOp::Load16 {
dst: args.next_rdwr()?,
src: args.next_rd()?,
}
}
"ld8" => {
BuiltinOp::Move8 {
BuiltinOp::Load8 {
dst: args.next_rdwr()?,
src: args.next_rd()?,
}
}
"ldn" => {
BuiltinOp::MoveMultiple {
BuiltinOp::LoadMultiple {
dst: args.next_wr()?,
src: args.next_rd()?,
count: args.next_rd()?,
@@ -225,6 +226,22 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
Sexp::Atom(Atom::QS(s), _) => {
LdsValue::Chars(s)
}
tok @ Sexp::Atom(Atom::S(_), _) => {
let pos = tok.pos().clone();
match parse_rd(tok, args.pcx)? {
Rd(RdData::ImmObject(v)) => {
LdsValue::Handle(RdObj::Imm(v))
}
Rd(RdData::RegObject(r)) => {
LdsValue::Handle(RdObj::Reg(r))
}
_ => {
return Err(CrsnError::Parse(
"Expected a handle, quoted string, or a tuple of values".into(),
pos));
}
}
}
Sexp::List(list, _) => {
let mut vals = vec![];
for v in list {
@@ -233,11 +250,13 @@ pub(crate) fn parse_op<'a>(op_pos: &SourcePosition, keyword: &str, mut args: Tok
LdsValue::Values(vals)
}
other => {
return Err(CrsnError::Parse("Expected quoted string or a tuple of values".into(), other.pos().clone()));
return Err(CrsnError::Parse(
"Expected a handle, quoted string, or a tuple of values".into(),
other.pos().clone()));
}
};
BuiltinOp::MoveSequence { dst, value }
BuiltinOp::LoadSequence { dst, value }
}
"xch" => {
@@ -359,15 +378,15 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
}
}
BuiltinOp::Delete(obj) => sexp::list(&[A("del"), A(obj)]),
BuiltinOp::Move { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]),
BuiltinOp::Move32 { dst, src } => sexp::list(&[A("ld32"), A(dst), A(src)]),
BuiltinOp::Move16 { dst, src } => sexp::list(&[A("ld16"), A(dst), A(src)]),
BuiltinOp::Move8 { dst, src } => sexp::list(&[A("ld8"), A(dst), A(src)]),
BuiltinOp::MoveMultiple { dst, src, count } => sexp::list(&[A("ldn"), A(dst), A(src), A(count)]),
BuiltinOp::Load { dst, src } => sexp::list(&[A("ld"), A(dst), A(src)]),
BuiltinOp::Load32 { dst, src } => sexp::list(&[A("ld32"), A(dst), A(src)]),
BuiltinOp::Load16 { dst, src } => sexp::list(&[A("ld16"), A(dst), A(src)]),
BuiltinOp::Load8 { dst, src } => sexp::list(&[A("ld8"), A(dst), A(src)]),
BuiltinOp::LoadMultiple { dst, src, count } => sexp::list(&[A("ldn"), A(dst), A(src), A(count)]),
BuiltinOp::Exchange { a, b } => sexp::list(&[A("xch"), A(a), A(b)]),
BuiltinOp::StoreFlags { dst } => sexp::list(&[A("stf"), A(dst)]),
BuiltinOp::LoadFlags { src } => sexp::list(&[A("ldf"), A(src)]),
BuiltinOp::MoveSequence { dst, value } => {
BuiltinOp::LoadSequence { dst, value } => {
match value {
LdsValue::Values(vals) => {
let mut vals: Vec<_> = vals.iter().map(A).collect();
@@ -378,6 +397,9 @@ pub(crate) fn to_sexp(op: &BuiltinOp) -> Sexp {
LdsValue::Chars(str) => {
sexp::list(&[A("lds"), A(dst), atom_qs(str)])
}
LdsValue::Handle(h) => {
sexp::list(&[A("lds"), A(dst), A(h)])
}
}
}
}
+10 -1
View File
@@ -15,6 +15,7 @@ use crate::runtime::run_thread::state::RunState;
use crate::runtime::run_thread::ThreadInfo;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use crate::asm::data::Wr;
mod eval_res;
@@ -105,7 +106,7 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
Ok(None)
}
/// Run-time method called to read an object (using the object handle syntax)
/// Run-time method called to read an object ("ld" and its variants, using the object handle syntax)
fn read_obj(&self, state: &mut RunState, handle: Value)
-> Result<Option<Value>, Fault>
{
@@ -113,6 +114,14 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
Ok(None)
}
/// Run-time method called to read all values from an object ("lds" using the object handle syntax)
fn read_obj_all(&self, state: &mut RunState, whandle: Wr, rhandle: Value)
-> Result<Option<()>, Fault>
{
// Default impl - we do not support reading this object
Ok(None)
}
/// Run-time method called to write an object (using the object handle syntax)
fn write_obj(&self, state: &mut RunState, handle: Value, value: Value) -> Result<Option<()>, Fault>
{
+1 -1
View File
@@ -91,7 +91,7 @@ impl RunState {
/// Read object handle value
pub fn read_obj(&mut self, rdo: impl Into<RdObj>) -> Result<Value, Fault> {
self.read(Rd::new(RdData::Register(rdo.into().reg())))
rdo.into().read(self)
}
/// Read a `Rd` value