refactored logic with Opcode enum, starting to support typed literals

This commit is contained in:
Skye Terran 2021-12-09 17:50:16 -08:00
parent cc04958955
commit 3cad6aa362
1 changed files with 66 additions and 50 deletions

View File

@ -28,8 +28,21 @@ use std::env;
// 0x1d: LERP (lerp n-2 to n-1 by n alpha) // 0x1d: LERP (lerp n-2 to n-1 by n alpha)
// 0x1e: MIN // 0x1e: MIN
// 0x1f: MAX // 0x1f: MAX
// Contextual: literal types
// 0x00: BOOL (boolean) # Example: LIT BOOL 0
// 0x01: INT (int) # Example: LIT INT 69
// 0x02: FLT (float) # Example: LIT FLT -90.0
// 0x03: VEC (vector) # Example: LIT VEC 1.0 -7.01 2.7
// ./slipcode Q:/Code/slipcompiler/Test.slb // ./slipcode Q:/Code/slipcompiler/Test.vcr
// Opcode enum
enum Opcode {
Generic,
Type,
Value
}
fn main() { fn main() {
println!("Slipcode | Skye Terran, 2021\n"); println!("Slipcode | Skye Terran, 2021\n");
@ -42,70 +55,73 @@ fn main() {
execute(&mut instructions, &mut values); execute(&mut instructions, &mut values);
} }
fn get_input() -> Vec<u8> {
println!("\nEnter instruction:");
let mut input = String::new();
io::stdin().read_line(&mut input)
.expect("Couldn't read input!");
println!("\n");
input.truncate(input.len() - 2);
let bytes = input.as_bytes();
bytes.to_vec()
}
fn execute(instructions: &mut Vec<u8>, values: &mut Vec<f32>) { fn execute(instructions: &mut Vec<u8>, values: &mut Vec<f32>) {
println!("Executing bytecode instructions...\n"); println!("Executing bytecode instructions...\n");
let mut iter = instructions.iter(); let mut iter = instructions.iter();
// Handle literals // Handle literals
let mut is_literal = false; let mut op_type: Opcode = Opcode::Generic;
let mut literal = [0u8; 4]; let mut literal = [0u8; 4];
let mut lit_digit = 0; let mut lit_digit = 0;
// Handle each opcode in order
loop { loop {
let byte_opt = iter.next(); let byte_opt = iter.next();
if is_literal { // Contextually handle opcodes depending on their type
if byte_opt.is_some() { match op_type {
// Treat the opcode as a literal type declaration
Opcode::Type => {
// Consume the literal type
let byte = byte_opt.unwrap(); let byte = byte_opt.unwrap();
// Record another of the literal's bytes
literal[lit_digit] = *byte;
// Continue consuming the literal // The following opcodes are expected to be a literal value
if lit_digit >= 3 { op_type = Opcode::Value;
let num = f32::from_bits(as_u32_be(&literal)); },
values.push(num); // Treat the opcode as a literal value
println!("LIT {:?}", num); Opcode::Value => {
println!("Values: {:?}\n", values); if byte_opt.is_some() {
is_literal = false; let byte = byte_opt.unwrap();
lit_digit = 0; // Record another of the literal's bytes
literal[lit_digit] = *byte;
// Continue consuming the literal
if lit_digit >= 3 {
let num = f32::from_bits(as_u32_be(&literal));
values.push(num);
println!("LIT {:?}", num);
println!("Values: {:?}\n", values);
op_type = Opcode::Generic;
lit_digit = 0;
} else {
lit_digit += 1;
}
} else { } else {
lit_digit += 1; break;
} }
} else { },
break; // Treat the opcode as a generic command
} _ => {
} else { if byte_opt.is_some() {
if byte_opt.is_some() { let byte = byte_opt.unwrap();
let byte = byte_opt.unwrap(); match byte {
match byte { 0x01 => op_type = Opcode::Type,
0x01 => is_literal = true, 0x02 => swap(values),
0x02 => swap(values), 0x03 => del(values),
0x03 => del(values), 0x04 => copy(values),
0x04 => copy(values), 0x10 => add(values),
0x10 => add(values), 0x11 => sub(values),
0x11 => sub(values), 0x12 => mul(values),
0x12 => mul(values), 0x19 => floor(values),
0x19 => floor(values), _ => break
_ => break }
// DEBUG - show the value stack upon every generic command
if let Opcode::Generic = op_type {
println!("Values: {:?}\n", values);
}
} else {
break;
} }
if !is_literal {
println!("Values: {:?}\n", values);
}
} else {
break;
} }
} }
} }