Add Bool and Char addressing modes
All checks were successful
per-push tests / build (push) Successful in 1m45s
per-push tests / test-frontend (push) Successful in 2m5s
per-push tests / test-utility (push) Successful in 2m12s
per-push tests / timed-decomposer-parse (push) Successful in 1m8s
per-push tests / test-backend (push) Successful in 1m17s

This commit adds addressing modes for boolean and character data.
The Address enum is extended, along with its TryFrom<u8> implementation
and its operand_size function. The access macro is extended to handle
the new modes. The CONST instruction can now create Char and Bool data.
The instructions.toml has information on the new addressing modes. Unit
tests have been added to test new CONST logic.

fixes: #41

Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
Ava Apples Affine 2025-08-09 04:45:56 +00:00
parent 4fb7e78c2a
commit e310b901c3
3 changed files with 76 additions and 25 deletions

View file

@ -170,6 +170,8 @@ impl VM {
Address::Oper4 => &self.oper[3],
Address::Stack => &self.stack[$oper.1],
Address::Numer => e!("cannot access constant numeric data"),
Address::Char => e!("cannot access constant char data"),
Address::Bool => e!("cannot access constant bool data"),
Address::Instr => e!("bad access to instruction data"),
}
};
@ -405,11 +407,14 @@ impl VM {
},
i::CONST => access!(&instr.1[0], {
let Operand(Address::Numer, num) = instr.1[1] else {
e!("illegal argument to CONST instruction");
};
Datum::Number(Number::Fra(Fraction(num as isize, 1))).into()
match instr.1[1].0 {
Address::Numer =>
Datum::Number(Number::Fra(Fraction(instr.1[1].1 as isize, 1)))
.into(),
Address::Bool => Datum::Bool(instr.1[1].1 > 0).into(),
Address::Char => Datum::Char(instr.1[1].1 as u8).into(),
_ => e!("illegal argument to CONST instruction"),
}
}),
i::MKVEC => self.expr = Datum::Vector(vec![]).into(),
@ -629,7 +634,7 @@ mod tests {
fn chk_err(&self, state: &VM) -> bool {
if let Datum::String(ref msg) = *state.errr {
let msg = unsafe { str::from_utf8_unchecked(msg) };
if msg == self.errr.unwrap() {
if self.errr.is_some() && msg == self.errr.unwrap() {
true
} else {
print!("expected error {:?}, got {:?}\n", self.errr, msg);
@ -1117,6 +1122,35 @@ mod tests {
assert!(case.test_passes(&vm));
}
#[test]
fn isa_consts() {
let mut vm = VM::from(Program(vec![
Instruction(i::CONST, vec![Operand(Address::Expr, 0),
Operand(Address::Numer, 1)]),
Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]),
Instruction(i::CONST, vec![Operand(Address::Expr, 0),
Operand(Address::Char, 'a' as u8 as usize)]),
Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]),
Instruction(i::CONST, vec![Operand(Address::Expr, 0),
Operand(Address::Bool, 1)]),
Instruction(i::PUSH, vec![Operand(Address::Expr, 0)]),
]));
let case = TestResult{
expr: None,
stack: vec![
(0, Datum::Bool(true).into()),
(1, Datum::Char('a' as u8).into()),
(2, Datum::Number(Number::Fra(Fraction(1, 1))).into()),
],
syms: vec![],
errr: None,
};
vm.run_program();
assert!(case.test_passes(&vm));
}
/*
#[test]
fn isa_index() {