| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- use crate::{
- error::{Error, Result},
- //prop::{Property, PropertySubType, PropertyType, PropertySExprValue},
- };
- use darkfi_serial::{
- serialize, Decodable, Encodable, ReadExt, SerialDecodable, SerialEncodable, WriteExt,
- };
- use std::{
- io::{Read, Write},
- sync::Arc,
- };
- #[derive(Clone, Debug, PartialEq, SerialEncodable, SerialDecodable)]
- pub enum SExprVal {
- Null,
- Bool(bool),
- Uint32(u32),
- Float32(f32),
- Str(String),
- }
- impl SExprVal {
- fn is_null(&self) -> bool {
- match self {
- Self::Null => true,
- _ => false,
- }
- }
- fn is_bool(&self) -> bool {
- match self {
- Self::Bool(v) => true,
- _ => false,
- }
- }
- fn is_u32(&self) -> bool {
- match self {
- Self::Uint32(v) => true,
- _ => false,
- }
- }
- fn is_f32(&self) -> bool {
- match self {
- Self::Float32(v) => true,
- _ => false,
- }
- }
- fn is_str(&self) -> bool {
- match self {
- Self::Str(v) => true,
- _ => false,
- }
- }
- fn as_bool(&self) -> Result<bool> {
- match self {
- Self::Bool(v) => Ok(*v),
- _ => Err(Error::PropertyWrongType),
- }
- }
- pub fn as_u32(&self) -> Result<u32> {
- match self {
- Self::Uint32(v) => Ok(*v),
- _ => Err(Error::PropertyWrongType),
- }
- }
- pub fn as_f32(&self) -> Result<f32> {
- match self {
- Self::Float32(v) => Ok(*v),
- _ => Err(Error::PropertyWrongType),
- }
- }
- fn as_str(&self) -> Result<String> {
- match self {
- Self::Str(v) => Ok(v.clone()),
- _ => Err(Error::PropertyWrongType),
- }
- }
- pub fn coerce_f32(&self) -> Result<f32> {
- match self {
- Self::Uint32(v) => Ok(*v as f32),
- Self::Float32(v) => Ok(*v),
- _ => Err(Error::PropertyWrongType),
- }
- }
- }
- #[derive(Debug, PartialEq)]
- pub struct SExprMachine<'a> {
- pub globals: Vec<(String, SExprVal)>,
- pub stmts: &'a SExprCode,
- }
- // Each item is a statement
- pub type SExprCode = Vec<Op>;
- #[derive(Debug, PartialEq)]
- pub enum Op {
- Null,
- Add((Box<Op>, Box<Op>)),
- Sub((Box<Op>, Box<Op>)),
- Mul((Box<Op>, Box<Op>)),
- Div((Box<Op>, Box<Op>)),
- ConstBool(bool),
- ConstUint32(u32),
- ConstFloat32(f32),
- ConstStr(String),
- LoadVar(String),
- //StoreVar((String, Box<Op>)),
- Min((Box<Op>, Box<Op>)),
- Max((Box<Op>, Box<Op>)),
- IsEqual((Box<Op>, Box<Op>)),
- LessThan((Box<Op>, Box<Op>)),
- Float32ToUint32(Box<Op>),
- }
- impl<'a> SExprMachine<'a> {
- pub fn call(&self) -> Result<SExprVal> {
- if self.stmts.is_empty() {
- return Ok(SExprVal::Null)
- }
- for i in 0..(self.stmts.len() - 1) {
- self.eval(&self.stmts[i])?;
- }
- self.eval(self.stmts.last().unwrap())
- }
- fn eval(&self, op: &Op) -> Result<SExprVal> {
- match op {
- Op::Null => Ok(SExprVal::Null),
- Op::Add((lhs, rhs)) => self.add(lhs, rhs),
- Op::Sub((lhs, rhs)) => self.sub(lhs, rhs),
- Op::Mul((lhs, rhs)) => self.mul(lhs, rhs),
- Op::Div((lhs, rhs)) => self.div(lhs, rhs),
- Op::ConstBool(val) => Ok(SExprVal::Bool(*val)),
- Op::ConstUint32(val) => Ok(SExprVal::Uint32(*val)),
- Op::ConstFloat32(val) => Ok(SExprVal::Float32(*val)),
- Op::ConstStr(val) => Ok(SExprVal::Str(val.clone())),
- Op::LoadVar(var) => self.load_var(var),
- //Op::StoreVar((var, val)) => self.store_var(var, val),
- Op::Min((lhs, rhs)) => self.min(lhs, rhs),
- Op::Max((lhs, rhs)) => self.max(lhs, rhs),
- Op::IsEqual((lhs, rhs)) => self.is_equal(lhs, rhs),
- Op::LessThan((lhs, rhs)) => self.less_than(lhs, rhs),
- Op::Float32ToUint32(val) => self.float32_to_uint32(val),
- }
- }
- fn add(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- return Ok(SExprVal::Uint32(lhs.as_u32().unwrap() + rhs.as_u32().unwrap()))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- Ok(SExprVal::Float32(lhs + rhs))
- }
- fn sub(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- return Ok(SExprVal::Uint32(lhs.as_u32().unwrap() - rhs.as_u32().unwrap()))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- Ok(SExprVal::Float32(lhs - rhs))
- }
- fn mul(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- return Ok(SExprVal::Uint32(lhs.as_u32().unwrap() * rhs.as_u32().unwrap()))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- Ok(SExprVal::Float32(lhs * rhs))
- }
- fn div(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- // Always coerce
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- Ok(SExprVal::Float32(lhs / rhs))
- }
- fn load_var(&self, var: &str) -> Result<SExprVal> {
- for (name, val) in &self.globals {
- if name == var {
- return Ok(val.clone())
- }
- }
- Err(Error::SExprGlobalNotFound)
- }
- //fn store_var(&mut self, var, val) {
- //}
- fn min(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- let lhs = lhs.as_u32().unwrap();
- let rhs = rhs.as_u32().unwrap();
- let min = if lhs < rhs { lhs } else { rhs };
- return Ok(SExprVal::Uint32(min))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- let min = if lhs < rhs { lhs } else { rhs };
- Ok(SExprVal::Float32(min))
- }
- fn max(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- let lhs = lhs.as_u32().unwrap();
- let rhs = rhs.as_u32().unwrap();
- let max = if lhs > rhs { lhs } else { rhs };
- return Ok(SExprVal::Uint32(max))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- let max = if lhs > rhs { lhs } else { rhs };
- Ok(SExprVal::Float32(max))
- }
- fn is_equal(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- return Ok(SExprVal::Bool(lhs.as_u32().unwrap() == rhs.as_u32().unwrap()))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- let is_equal = (lhs - rhs).abs() < f32::EPSILON;
- Ok(SExprVal::Bool(is_equal))
- }
- fn less_than(&self, lhs: &Op, rhs: &Op) -> Result<SExprVal> {
- let lhs = self.eval(lhs)?;
- let rhs = self.eval(rhs)?;
- if lhs.is_u32() && rhs.is_u32() {
- return Ok(SExprVal::Bool(lhs.as_u32().unwrap() < rhs.as_u32().unwrap()))
- }
- let lhs = lhs.coerce_f32()?;
- let rhs = rhs.coerce_f32()?;
- Ok(SExprVal::Bool(lhs < rhs))
- }
- fn float32_to_uint32(&self, val: &Op) -> Result<SExprVal> {
- let val = self.eval(val)?;
- if val.is_u32() {
- return Ok(SExprVal::Uint32(val.as_u32()?))
- }
- Ok(SExprVal::Uint32(val.as_f32()? as u32))
- }
- }
- impl Encodable for Op {
- fn encode<S: Write>(&self, s: &mut S) -> std::result::Result<usize, std::io::Error> {
- let mut len = 0;
- match self {
- Self::Null => {
- len += 0u8.encode(s)?;
- }
- Self::Add((lhs, rhs)) => {
- len += 1u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::Sub((lhs, rhs)) => {
- len += 2u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::Mul((lhs, rhs)) => {
- len += 3u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::Div((lhs, rhs)) => {
- len += 4u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::ConstBool(val) => {
- len += 5u8.encode(s)?;
- len += val.encode(s)?;
- }
- Self::ConstUint32(val) => {
- len += 6u8.encode(s)?;
- len += val.encode(s)?;
- }
- Self::ConstFloat32(val) => {
- len += 7u8.encode(s)?;
- len += val.encode(s)?;
- }
- Self::ConstStr(val) => {
- len += 8u8.encode(s)?;
- len += val.encode(s)?;
- }
- Self::LoadVar(var) => {
- len += 9u8.encode(s)?;
- len += var.encode(s)?;
- }
- // StoreVar
- Self::Min((lhs, rhs)) => {
- len += 11u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::Max((lhs, rhs)) => {
- len += 12u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::IsEqual((lhs, rhs)) => {
- len += 13u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::LessThan((lhs, rhs)) => {
- len += 14u8.encode(s)?;
- len += lhs.encode(s)?;
- len += rhs.encode(s)?;
- }
- Self::Float32ToUint32(val) => {
- len += 15u8.encode(s)?;
- len += val.encode(s)?;
- }
- }
- Ok(len)
- }
- }
- impl Decodable for Op {
- fn decode<D: Read>(d: &mut D) -> std::result::Result<Self, std::io::Error> {
- let op_type = d.read_u8()?;
- let self_ = match op_type {
- 0 => Self::Null,
- 1 => Self::Add((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 2 => Self::Sub((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 3 => Self::Mul((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 4 => Self::Div((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 5 => Self::ConstBool(d.read_bool()?),
- 6 => Self::ConstUint32(d.read_u32()?),
- 7 => Self::ConstFloat32(d.read_f32()?),
- 8 => Self::ConstStr(String::decode(d)?),
- 9 => Self::LoadVar(String::decode(d)?),
- // StoreVar
- 11 => Self::Min((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 12 => Self::Max((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 13 => Self::IsEqual((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 14 => Self::LessThan((Box::new(Self::decode(d)?), Box::new(Self::decode(d)?))),
- 15 => Self::Float32ToUint32(Box::new(Self::decode(d)?)),
- _ => return Err(std::io::Error::new(std::io::ErrorKind::Other, "Invalid Op type")),
- };
- Ok(self_)
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use darkfi_serial::{deserialize, serialize};
- #[test]
- fn seval() {
- let machine = SExprMachine {
- globals: vec![
- ("sw".to_string(), SExprVal::Uint32(110u32)),
- ("sh".to_string(), SExprVal::Uint32(4u32)),
- ],
- stmts: &vec![Op::Add((
- Box::new(Op::ConstUint32(5)),
- Box::new(Op::Div((
- Box::new(Op::LoadVar("sw".to_string())),
- Box::new(Op::ConstUint32(2)),
- ))),
- ))],
- };
- assert_eq!(machine.call().unwrap(), SExprVal::Float32(60.));
- }
- #[test]
- fn encdec_code() {
- let code = Op::Add((
- Box::new(Op::ConstUint32(5)),
- Box::new(Op::Div((
- Box::new(Op::LoadVar("sw".to_string())),
- Box::new(Op::ConstUint32(2)),
- ))),
- ));
- let code_s = serialize(&code);
- let code2 = deserialize::<Op>(&code_s).unwrap();
- assert_eq!(code, code2);
- }
- }
|