String Instructions
All checks were successful
per-push tests / build (push) Successful in 47s
per-push tests / test-utility (push) Successful in 53s
per-push tests / test-frontend (push) Successful in 59s
per-push tests / test-backend (push) Successful in 43s
per-push tests / timed-decomposer-parse (push) Successful in 51s
All checks were successful
per-push tests / build (push) Successful in 47s
per-push tests / test-utility (push) Successful in 53s
per-push tests / test-frontend (push) Successful in 59s
per-push tests / test-backend (push) Successful in 43s
per-push tests / timed-decomposer-parse (push) Successful in 51s
The following instructions are modified to act on strings: - INDEX: Now pulls a char out at index - SUBSL: Now pulls a substring out of a source string - INSER: Now inserts a char into a string at index - LENGTH: Now returns length of a string In addition to the above instructions, additional instructions are now implemented to handle strings: - CONCAT: appends a string onto another string - S_APPEND: appends a char on to the end of a string Fixes: #38 Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
parent
63554191f8
commit
ddb49788af
3 changed files with 81 additions and 43 deletions
107
hyphae/src/vm.rs
107
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");
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue