Number-to-ByteVector-conversion #44

Merged
affine merged 7 commits from Number-to-ByteVector-conversion into main 2025-12-04 12:09:45 -08:00
2 changed files with 70 additions and 9 deletions

View file

@ -16,7 +16,7 @@
*/ */
use organelle::{Fraction, Number, Numeric}; use organelle::{Float, Fraction, Number, Numeric};
use crate::hmap::QuickMap; use crate::hmap::QuickMap;
use crate::stackstack::StackStack; use crate::stackstack::StackStack;
@ -399,6 +399,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], { i::NTOC => access!(&instr.1[0], {
if let Datum::Number(snum) = **access!(&instr.1[0]) { if let Datum::Number(snum) = **access!(&instr.1[0]) {
let n = snum.make_inexact(); let n = snum.make_inexact();
@ -1098,16 +1120,16 @@ mod tests {
#[test] #[test]
fn isa_conversions() { fn isa_conversions() {
let mut vm = VM::from(Program(vec![], vec![ let mut vm = VM::from(Program(vec![], vec![
// load from stack into expr // load from stack into expr
Instruction(i::DUPL, vec![Operand(Address::Stack, 0), Instruction(i::DUPL, vec![Operand(Address::Stack, 0),
Operand(Address::Expr, 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::CTOS, vec![Operand(Address::Expr, 0)]),
Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]),
// reset expr to original char // reset expr to original char
Instruction(i::DUPL, vec![Operand(Address::Stack, 1), Instruction(i::DUPL, vec![Operand(Address::Stack, 1),
Operand(Address::Expr, 0)]), Operand(Address::Expr, 0)]),
@ -1123,9 +1145,18 @@ mod tests {
Instruction(i::NTOE, vec![Operand(Address::Expr, 0)]), Instruction(i::NTOE, vec![Operand(Address::Expr, 0)]),
Instruction(i::PUSH, 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 // create a char and push to stack
Instruction(i::NTOC, vec![Operand(Address::Expr, 0)]), Instruction(i::NTOC, vec![Operand(Address::Expr, 0)]),
Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]),
])).with_stack({ ])).with_stack({
let mut i = StackStack::new(); let mut i = StackStack::new();
i.push_current_stack(Datum::Char(b'a').into()); i.push_current_stack(Datum::Char(b'a').into());
@ -1135,12 +1166,14 @@ mod tests {
let case = TestResult{ let case = TestResult{
expr: None, expr: None,
stack: vec![ stack: vec![
(0, Datum::Char(b'a').into()), (0, Datum::Char(b'a').into()), // NTOC
(1, Datum::Number(Number::Fra(Fraction(97, 1))).into()), (1, Datum::Number(Number::Flt(Float(97.0))).into()), // BVTON
(2, Datum::Number(Number::Flt(Float(97.0))).into()), (2, Datum::ByteVector(vec![0, 0, 0, 0, 0, 64, 88, 64]).into()), // NTOBV
(3, Datum::Number(Number::Fra(Fraction(97, 1))).into()), (3, Datum::Number(Number::Fra(Fraction(97, 1))).into()), // NTOE
(4, Datum::String(vec![b'a']).into()), (4, Datum::Number(Number::Flt(Float(97.0))).into()), // NTOI
(5, Datum::Char(b'a').into()), (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![], syms: vec![],
errr: None, errr: None,

View file

@ -641,6 +641,34 @@ character byte.
Requires mutable access to input address. 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]] [[instructions]]
name = "ntoc" name = "ntoc"
args = ["src"] args = ["src"]