diff --git a/hyphae/instructions.toml b/hyphae/instructions.toml index c65a533..66b8099 100644 --- a/hyphae/instructions.toml +++ b/hyphae/instructions.toml @@ -312,3 +312,15 @@ name = "cdr" args = ["list"] output = "returns last element in cons cell" description = "takes an AST and returns last element in top level cons cell" + +[[instructions]] +name = "concat" +args = ["string_l", "string_r"] +output = "string_l+string_r" +description = "concatenates string r to string l and returns a new string" + +[[instructions]] +name = "s_append" +args = ["parent", "child"] +output = "" +description = "append in place child character into parent string" diff --git a/hyphae/src/heap.rs b/hyphae/src/heap.rs index 1e60e3c..6d79215 100644 --- a/hyphae/src/heap.rs +++ b/hyphae/src/heap.rs @@ -17,7 +17,6 @@ use core::ops::{Index, Deref, DerefMut}; use core::ptr::NonNull; -use core::cell::RefCell; use alloc::rc::Rc; use alloc::vec::Vec; @@ -141,8 +140,8 @@ pub enum Datum { Symbol(String), Char(u8), String(Vec), - Vector(RefCell>>), - ByteVector(RefCell>), + Vector(Vec>), + ByteVector(Vec), None } diff --git a/hyphae/src/vm.rs b/hyphae/src/vm.rs index 4fe21d3..c6ad370 100644 --- a/hyphae/src/vm.rs +++ b/hyphae/src/vm.rs @@ -24,7 +24,6 @@ use crate::instr as i; use crate::util::{Operand, Program, Address}; use crate::heap::{Gc, Datum, Cons}; -use core::cell::RefCell; use core::ops::DerefMut; use alloc::vec; @@ -345,8 +344,10 @@ impl VM { Datum::Number(Number::Fra(Fraction(num as isize, 1))).into() }), - i::MKVEC => self.expr = Datum::Vector(RefCell::from(vec![])).into(), - i::MKBVEC => self.expr = Datum::ByteVector(RefCell::from(vec![])).into(), + i::MKVEC => self.expr = Datum::Vector(vec![]).into(), + + i::MKBVEC => self.expr = Datum::ByteVector(vec![]).into(), + i::INDEX => { let Datum::Number(ref idx) = **access!(&instr.1[1]) else { e!("illegal argument to INDEX instruction"); @@ -357,31 +358,28 @@ impl VM { } let idx = idx.0.trunc() as usize; - match **access!(&instr.1[0]) { - Datum::Vector(ref v) => { - let a = (*v.borrow()[idx].clone()).clone(); - self.expr = a.into(); - }, - Datum::ByteVector(ref bv) => { - let a = Datum::Char(bv.borrow()[idx]); - self.expr = a.into(); - }, + match *access!(&instr.1[0]).clone() { + Datum::Vector(ref v) => + self.expr = (*v[idx].clone()).clone().into(), + Datum::ByteVector(ref bv) => + self.expr = Datum::Char(bv[idx]).into(), + Datum::String(ref s) => + self.expr = Datum::Char(s[idx]).into(), Datum::Cons(ref l) => self.expr = l[idx].clone(), _ => e!("illegal argument to INDEX instruction") }; }, i::LENGTH => match **access!(&instr.1[0]) { - Datum::Vector(ref v) => { - let a = Datum::Number(Number::Fra(Fraction( - v.borrow().len() as isize, 1))); - self.expr = a.into(); - }, - Datum::ByteVector(ref bv) => { - let a = Datum::Number(Number::Fra(Fraction( - bv.borrow().len() as isize, 1))); - self.expr = a.into(); - }, + Datum::Vector(ref v) => + self.expr = Datum::Number(Number::Fra(Fraction( + v.len() as isize, 1))).into(), + Datum::ByteVector(ref bv) => + self.expr = Datum::Number(Number::Fra(Fraction( + bv.len() as isize, 1))).into(), + Datum::String(ref s) => + self.expr = Datum::Number(Number::Fra(Fraction( + s.len() as isize, 1))).into(), Datum::Cons(ref l) => self.expr = Datum::Number(Number::Fra(Fraction(l.len() as isize, 1))) .into(), @@ -411,17 +409,14 @@ impl VM { let st = st.0.trunc() as usize; let ed = ed.0.trunc() as usize; - match **access!(&instr.1[0]) { - Datum::Vector(ref v) => { - let a = Datum::Vector(RefCell::from(v.borrow()[st..ed].to_vec())); - self.expr = a.into(); - }, - Datum::ByteVector(ref bv) => { - let a = Datum::ByteVector(RefCell::from(bv.borrow()[st..ed].to_vec())); - self.expr = a.into(); - }, - - Datum::Cons(ref a) => self.expr = + match access!(&instr.1[0]).clone().deref_mut() { + Datum::Vector(v) => + self.expr = Datum::Vector(v[st..ed].to_vec()).into(), + Datum::ByteVector(bv) => + self.expr = Datum::ByteVector(bv[st..ed].to_vec()).into(), + Datum::String(s) => + self.expr = Datum::String(s[st..ed].to_vec()).into(), + Datum::Cons(a) => self.expr = Datum::Cons(a.subsl(st as isize, ed as isize)).into(), _ => e!("illegal argument to SUBSL instruction") }; @@ -439,18 +434,22 @@ impl VM { let idx = idx.0.trunc() as usize; - match **access!(&instr.1[0]) { - Datum::Vector(ref v) => { - v.borrow_mut() - .insert(idx, access!(&instr.1[1]) - .deep_copy()); + match access!(&instr.1[0]).clone().deref_mut() { + Datum::Vector(v) => { + v.insert(idx, access!(&instr.1[1]).clone()); }, - Datum::ByteVector(ref bv) => { + Datum::ByteVector(bv) => { let Datum::Char(b) = **access!(&instr.1[1]) else { e!("INSER instruction can only insert a byte into a bytevector"); }; - bv.borrow_mut().insert(idx, b); + bv.insert(idx, b); }, + Datum::String(st) => { + let Datum::Char(b) = **access!(&instr.1[1]) else { + e!("INSER instruction can only insert a char into a string"); + }; + st.insert(idx, b); + } _ => e!("illegal argument to INSER instruction") } }, @@ -487,6 +486,34 @@ impl VM { } }, + i::CONCAT => { + let Datum::String(ref left) = **access!(&instr.1[0]) else { + e!("illegal argument to CONCAT instruction"); + }; + + let Datum::String(ref right) = **access!(&instr.1[1]) else { + e!("illegal argument to CONCAT instruction"); + }; + + let (left, right) = unsafe { (str::from_utf8_unchecked(left).to_owned(), + str::from_utf8_unchecked(right)) }; + + self.expr = Datum::String((left + right).as_bytes().to_vec()).into(); + }, + + i::S_APPEND => { + let mut left = access!(&instr.1[0]).clone(); + let Datum::String(left) = left.deref_mut() else { + e!("illegal argument to S_APPEND instruction"); + }; + + let Datum::Char(right) = **access!(&instr.1[1]) else { + e!("illegal argument to S_APPEND instruction"); + }; + + left.push(right); + }, + _ => { e!("illegal instruction"); },