148 lines
6.2 KiB
Rust
148 lines
6.2 KiB
Rust
use crate::{instructions, stack::{Instruction, Stack, StackVec}};
|
|
|
|
fn find_labels(stack: &mut Stack) {
|
|
while stack.program_counter < (stack.program.len() as u16) {
|
|
let label = &stack.program[stack.program_counter as usize];
|
|
stack.program_counter += 1;
|
|
|
|
if !label.name.starts_with('@') {
|
|
continue;
|
|
}
|
|
|
|
if stack.labels[label.data as usize].is_some() {
|
|
eprintln!("Label {} already defined", label.data);
|
|
std::process::exit(2);
|
|
}
|
|
|
|
if label.data == 0 {
|
|
stack.labels[0] = Some(stack.program_counter as i16);
|
|
continue;
|
|
}
|
|
|
|
stack.labels[label.data as usize] = Some(stack.program_counter as i16);
|
|
}
|
|
|
|
stack.program_counter = stack.labels[0].unwrap_or(0) as u16;
|
|
}
|
|
|
|
fn find_prefix_operators(instruction: &mut Instruction, memory: &mut StackVec) {
|
|
match instruction.name.chars().nth(0) {
|
|
Some('|') => {
|
|
instruction.name = instruction.name.chars().skip(1).collect();
|
|
instruction.data = memory.pop();
|
|
},
|
|
Some('^') => {
|
|
instruction.name = instruction.name.chars().skip(1).collect();
|
|
|
|
if instruction.name.chars().nth(0) != Some('#') {
|
|
println!("{0} {1}", instruction.name, instruction.data.to_string());
|
|
} else if instruction.arg.is_empty() {
|
|
println!("{}", instruction.name);
|
|
} else {
|
|
println!("{0} {1}", instruction.name, instruction.arg);
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name: String) {
|
|
find_labels(stack);
|
|
|
|
while let Some(mut instruction) = stack.program.get_mut(stack.program_counter as usize) {
|
|
stack.program_counter += 1;
|
|
|
|
find_prefix_operators(&mut instruction, &mut stack.memory);
|
|
|
|
if instruction.name.starts_with('@') {
|
|
continue;
|
|
}
|
|
|
|
match instruction.name.as_str() {
|
|
// Stack operations
|
|
"push" => instructions::push::push(&mut stack.memory, instruction.data),
|
|
"pop" => instructions::pop::pop(&mut stack.memory),
|
|
"dup" => instructions::dup::dup(&mut stack.memory),
|
|
"swap" => instructions::swap::swap(&mut stack.memory),
|
|
"pick" => instructions::pick::pick(&mut stack.memory, instruction.data),
|
|
|
|
// Math
|
|
"add" => instructions::add::add(&mut stack.memory),
|
|
"sub" => instructions::sub::sub(&mut stack.memory),
|
|
"mul" => instructions::mul::mul(&mut stack.memory),
|
|
"div" => instructions::div::div(&mut stack.memory),
|
|
"mod" => instructions::modulo::modulo(&mut stack.memory),
|
|
|
|
// Logic
|
|
"and" => instructions::and::and(&mut stack.memory),
|
|
"or" => instructions::or::or(&mut stack.memory),
|
|
"xor" => instructions::xor::xor(&mut stack.memory),
|
|
"nand" => instructions::nand::nand(&mut stack.memory),
|
|
"not" => instructions::not::not(&mut stack.memory),
|
|
|
|
// Bitwise
|
|
"band" => instructions::band::band(&mut stack.memory),
|
|
"bor" => instructions::bor::bor(&mut stack.memory),
|
|
"bxor" => instructions::bxor::bxor(&mut stack.memory),
|
|
"bnand" => instructions::bnand::bnand(&mut stack.memory),
|
|
"bnot" => instructions::not::not(&mut stack.memory),
|
|
|
|
// Labels
|
|
"jmp" => instructions::jmp::jmp(&mut stack.labels, &mut stack.program_counter, instruction.data),
|
|
"jnz" => instructions::jnz::jnz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
|
"jz" => instructions::jz::jz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
|
"kjnz" => instructions::kjnz::kjnz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
|
"kjz" => instructions::kjz::kjz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
|
|
|
// Input/Output
|
|
"putc" => instructions::putc::putc(&mut stack.memory),
|
|
"getc" => instructions::getc::getc(&mut stack.memory),
|
|
"scan" => instructions::scan::scan(&mut stack.memory),
|
|
"meow" => instructions::meow::meow(&mut stack.memory),
|
|
"#print" => instructions::print::print(instruction.arg.clone()),
|
|
"$print" => instructions::print::print(instruction.arg.clone()),
|
|
"#println" => instructions::println::println(instruction.arg.clone()),
|
|
"$println" => instructions::println::println(instruction.arg.clone()),
|
|
|
|
// Modules
|
|
"args" => instructions::args::args(&mut stack.memory, &mut origin_stack, instruction.data),
|
|
"#exec" => {
|
|
let arg = instruction.arg.clone();
|
|
instructions::exec::exec(stack, arg, mod_name.clone())
|
|
},
|
|
|
|
// Self-modifying
|
|
|
|
"#insert" => {
|
|
let arg = instruction.arg.clone();
|
|
let data = instruction.data.clone();
|
|
instructions::insert::insert(&mut stack.program, arg, data)
|
|
},
|
|
|
|
// Special
|
|
"dump" => instructions::dump::dump(&mut stack.memory),
|
|
"size" => instructions::size::size(&mut stack.memory),
|
|
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
|
"#expr" => instructions::expr::expr(&mut stack.memory, instruction.arg.clone()),
|
|
"nop" => continue,
|
|
"quit" => break,
|
|
"exit" => instructions::exit::exit(instruction.data),
|
|
|
|
// Platform-specific
|
|
#[cfg(target_family = "unix")]
|
|
"_unix_random" => instructions::_unix_random::_unix_random(&mut stack.memory),
|
|
|
|
#[cfg(not(target_family = "unix"))]
|
|
"_unix_random" => instructions::random::random(&mut stack.memory),
|
|
|
|
// Labast-specific
|
|
"random" => instructions::random::random(&mut stack.memory),
|
|
|
|
_ => {
|
|
eprintln!("Unknown instruction: {}", instruction.name);
|
|
std::process::exit(2);
|
|
}
|
|
}
|
|
}
|
|
}
|