diff --git a/hyphae/src/vm.rs b/hyphae/src/vm.rs index 9372d16..77b85ad 100644 --- a/hyphae/src/vm.rs +++ b/hyphae/src/vm.rs @@ -16,7 +16,7 @@ */ -use organelle::{Fraction, Number, Numeric}; +use organelle::{Float, Fraction, Number, Numeric}; use crate::hmap::QuickMap; use crate::stackstack::StackStack; @@ -391,6 +391,28 @@ impl VM { } }), + i::NTOBV => access!(&instr.1[0], { + if let Datum::Number(snum) = **access!(&instr.1[0]) { + let n = snum.make_inexact(); + if !snum.is_exact() || n.0.fract() != 0.0 || + n.0 > u8::MAX.into() || n.0 < 0.0 { + e!("input to NTOBV cannot cleanly convert"); + } + Datum::ByteVector(n.0.to_ne_bytes().to_vec()).into() + } else { + e!("illegal argument to NTOBV instruction"); + } + }), + + i::BVTON => access!(&instr.1[0], { + if let Datum::ByteVector(sbv) = &**access!(&instr.1[0]) { + let sf64 = f64::from_ne_bytes(sbv.clone().try_into().unwrap()); + Datum::Number(Number::Flt(Float(sf64))).into() + } else { + e!("illegal argument to BVTON instruction"); + } + }), + i::NTOC => access!(&instr.1[0], { if let Datum::Number(snum) = **access!(&instr.1[0]) { let n = snum.make_inexact(); @@ -1090,16 +1112,16 @@ mod tests { #[test] fn isa_conversions() { let mut vm = VM::from(Program(vec![], vec![ + // load from stack into expr Instruction(i::DUPL, vec![Operand(Address::Stack, 0), Operand(Address::Expr, 0)]), - // create a strunct and push to stack + // create a struct and push to stack Instruction(i::CTOS, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), // reset expr to original char - Instruction(i::DUPL, vec![Operand(Address::Stack, 1), Operand(Address::Expr, 0)]), @@ -1115,9 +1137,18 @@ mod tests { Instruction(i::NTOE, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), + // convert to ByteVector and push to stack + Instruction(i::NTOBV, vec![Operand(Address::Expr, 0)]), + Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), + + // convert back to inexact and push to stack + Instruction(i::BVTON, vec![Operand(Address::Expr, 0)]), + Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), + // create a char and push to stack Instruction(i::NTOC, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), + ])).with_stack({ let mut i = StackStack::new(); i.push_current_stack(Datum::Char(b'a').into()); @@ -1127,12 +1158,14 @@ mod tests { let case = TestResult{ expr: None, stack: vec![ - (0, Datum::Char(b'a').into()), - (1, Datum::Number(Number::Fra(Fraction(97, 1))).into()), - (2, Datum::Number(Number::Flt(Float(97.0))).into()), - (3, Datum::Number(Number::Fra(Fraction(97, 1))).into()), - (4, Datum::String(vec![b'a']).into()), - (5, Datum::Char(b'a').into()), + (0, Datum::Char(b'a').into()), // NTOC + (1, Datum::Number(Number::Flt(Float(97.0))).into()), // BVTON + (2, Datum::ByteVector(vec![0, 0, 0, 0, 0, 64, 88, 64]).into()), // NTOBV + (3, Datum::Number(Number::Fra(Fraction(97, 1))).into()), // NTOE + (4, Datum::Number(Number::Flt(Float(97.0))).into()), // NTOI + (5, Datum::Number(Number::Fra(Fraction(97, 1))).into()), // CTON + (6, Datum::String(vec![b'a']).into()), // CTOS + (7, Datum::Char(b'a').into()), // DUPL ], syms: vec![], errr: None, diff --git a/hyphae/vm.toml b/hyphae/vm.toml index b445a25..9b2d5d5 100644 --- a/hyphae/vm.toml +++ b/hyphae/vm.toml @@ -641,6 +641,34 @@ character byte. Requires mutable access to input address. """ +[[instructions]] +name = "ntobv" +args = ["src"] +output = "" +description = """ +The ntobv instruction accepts a single number input. This operand is overwritten +by a new number datum that represents the inexact form of the source number. + +The inexact form is a normalization of fraction or scientific notation datum to +float datum casted to ByteVector datum. + +Requires mutable access to input address. +""" + +[[instructions]] +name = "bvton" +args = ["src"] +output = "" +description = """ +The bvton instruction accepts a byte vector input. This operand is overwritten +by a new number datum that represents the inexact form of the source byte vector. + +The normalized fraction or scientific notation data represented in a +ByteVector datum is casted to an inexact floating point number. + +Requires mutable access to input address. +""" + [[instructions]] name = "ntoc" args = ["src"]