From f48867db4233490e05a023db549d70f075b735ee Mon Sep 17 00:00:00 2001 From: Ava Affine Date: Sat, 9 Aug 2025 05:23:45 +0000 Subject: [PATCH] VM Bytecode char to string instructions New instrucions: CTOS and MKSTR. CTOS creates a string containing a single (input) character. MKSTR creates a new blank string. Unit tests included. fixes: #42 Signed-off-by: Ava Affine --- hyphae/instructions.toml | 22 ++++++++++++++++++++++ hyphae/src/vm.rs | 36 +++++++++++++++++++++++------------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/hyphae/instructions.toml b/hyphae/instructions.toml index 2f8d3e2..9fd0b38 100644 --- a/hyphae/instructions.toml +++ b/hyphae/instructions.toml @@ -1,3 +1,13 @@ +# TODO: add the following info +# - introductory VM info (description, list of components) +# - info on the different data types +# - info on garbage collection +# - info on program execution +# - info on error handling +# - info on traps +# - info on numbers +# - info on symtable (and its uses) + [[addressing_modes]] name = "expr" mutable = true @@ -275,6 +285,12 @@ args = ["src"] output = "" description = "decrements number at source" +[[instructions]] +name = "ctos" +args = ["src"] +output = "" +description = "mutates a char datum into a string datum" + [[instructions]] name = "cton" args = ["src"] @@ -317,6 +333,12 @@ args = [] output = "a blank bytevector" description = "creates a blank bytevector" +[[instructions]] +name = "mkstr" +args = [] +output = "an empty string" +description = "creates a new empty string" + [[instructions]] name = "index" args = ["collection", "index"] diff --git a/hyphae/src/vm.rs b/hyphae/src/vm.rs index ffa9fbd..020fb91 100644 --- a/hyphae/src/vm.rs +++ b/hyphae/src/vm.rs @@ -369,6 +369,16 @@ impl VM { }), // byte/char to and from number conversions + i::CTOS => access!(&instr.1[0], { + if let Datum::Char(schr) = **access!(&instr.1[0]) { + let mut v = vec![]; + v.push(schr); + Datum::String(v).into() + } else { + e!("illegal argument to CTOS instruction"); + } + }), + i::CTON => access!(&instr.1[0], { if let Datum::Char(schr) = **access!(&instr.1[0]) { Datum::Number(Number::Fra(Fraction(schr as isize, 1))).into() @@ -421,6 +431,8 @@ impl VM { i::MKBVEC => self.expr = Datum::ByteVector(vec![]).into(), + i::MKSTR => self.expr = Datum::String(vec![]).into(), + i::INDEX => { let Datum::Number(ref idx) = **access!(&instr.1[1]) else { e!("illegal argument to INDEX instruction"); @@ -1067,23 +1079,20 @@ mod tests { #[test] fn isa_conversions() { - /* program: - * dupl %0, $ex - * cton $ex - * push $ex - * ntoc $ex - * push $ex - * ntoi $ex - * push $ex - * ntoe $ex - * push $ex - */ - let mut vm = VM::from(Program(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 + 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)]), + // create a number and push to stack Instruction(i::CTON, vec![Operand(Address::Expr, 0)]), Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]), @@ -1112,7 +1121,8 @@ mod tests { (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::Char(b'a').into()), + (4, Datum::String(vec![b'a']).into()), + (5, Datum::Char(b'a').into()), ], syms: vec![], errr: None,