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); } } } }