forked from n3tael/labast
обновление 1.0.5
* стек теперь не бесконечный. задать можно через аргумент cli (максимум 65535, дефолт: 256)
This commit is contained in:
parent
0eb3af2c47
commit
d6e290f916
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
/archive
|
|
||||||
/bin
|
/bin
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -10,7 +10,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "labast"
|
name = "labast"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"pico-args",
|
"pico-args",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "labast"
|
name = "labast"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
authors = [ "n3tael" ]
|
authors = [ "n3tael" ]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A zero-dependencies Labaski interpreter written in Rust."
|
description = "A Labaski interpreter written in Rust."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
publish = false
|
publish = false
|
||||||
|
@ -3,7 +3,9 @@ echo Building for Windows...
|
|||||||
cargo build --release
|
cargo build --release
|
||||||
echo Building for Linux...
|
echo Building for Linux...
|
||||||
cargo zigbuild --release --target x86_64-unknown-linux-gnu
|
cargo zigbuild --release --target x86_64-unknown-linux-gnu
|
||||||
echo Copy to bin...
|
echo Copy binaries to bin folder...
|
||||||
copy target\release\labast.exe bin\ /Y
|
copy target\release\labast.exe bin\ /Y
|
||||||
copy target\x86_64-unknown-linux-gnu\release\labast bin\ /Y
|
copy target\x86_64-unknown-linux-gnu\release\labast bin\ /Y
|
||||||
|
echo Creating source code tar.gz archive...
|
||||||
|
tar --exclude="./bin" --exclude="./target" --exclude=".git" -cvzf bin\labast-latest.tar.gz *
|
||||||
echo Done!
|
echo Done!
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
@ 2
|
@ 2
|
||||||
sub
|
sub
|
||||||
meow dkdkd
|
meow
|
||||||
quit
|
quit
|
||||||
|
|
||||||
@ 3
|
@ 3
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
pub enum StackError {
|
||||||
|
StackOverflow,
|
||||||
|
StackUnderflow,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for StackError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
StackError::StackOverflow => write!(f, "Stack overflow!"),
|
||||||
|
StackError::StackUnderflow => write!(f, "Stack underflow!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum RunError {
|
pub enum RunError {
|
||||||
RequestArgsInMainModule,
|
RequestArgsInMainModule,
|
||||||
ExecuteItself(String),
|
ExecuteItself(String),
|
||||||
@ -11,7 +25,6 @@ pub enum RunError {
|
|||||||
FailToReadLineFromConsole,
|
FailToReadLineFromConsole,
|
||||||
UnknownLabel(u16),
|
UnknownLabel(u16),
|
||||||
InvalidExpressionUnknownOperator(String),
|
InvalidExpressionUnknownOperator(String),
|
||||||
MemoryEmpty,
|
|
||||||
AttemptToInsertHashOrStringInst,
|
AttemptToInsertHashOrStringInst,
|
||||||
AttemptToInsertEmptyConst,
|
AttemptToInsertEmptyConst,
|
||||||
AttemptToInsertALabel
|
AttemptToInsertALabel
|
||||||
@ -30,7 +43,6 @@ impl Display for RunError {
|
|||||||
RunError::FailToReadLineFromConsole => write!(f, "Failed to read line from console"),
|
RunError::FailToReadLineFromConsole => write!(f, "Failed to read line from console"),
|
||||||
RunError::UnknownLabel(label_name) => write!(f, "Unknown label: {}", label_name),
|
RunError::UnknownLabel(label_name) => write!(f, "Unknown label: {}", label_name),
|
||||||
RunError::InvalidExpressionUnknownOperator(name) => write!(f, "Invalid expression: unknown operator '{}'", name),
|
RunError::InvalidExpressionUnknownOperator(name) => write!(f, "Invalid expression: unknown operator '{}'", name),
|
||||||
RunError::MemoryEmpty => write!(f, "No elements in memory!"),
|
|
||||||
RunError::AttemptToInsertHashOrStringInst => write!(f, "Attempt to insert a hash/string-instruction"),
|
RunError::AttemptToInsertHashOrStringInst => write!(f, "Attempt to insert a hash/string-instruction"),
|
||||||
RunError::AttemptToInsertEmptyConst => write!(f, "Attempt to insert an empty constant"),
|
RunError::AttemptToInsertEmptyConst => write!(f, "Attempt to insert an empty constant"),
|
||||||
RunError::AttemptToInsertALabel => write!(f, "Attempt to insert a label"),
|
RunError::AttemptToInsertALabel => write!(f, "Attempt to insert a label"),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{errors::RunError, instructions, stack::{Instruction, Stack}};
|
use crate::{instructions, stack::{Instruction, Stack, StackVec}};
|
||||||
|
|
||||||
fn find_labels(stack: &mut Stack) {
|
fn find_labels(stack: &mut Stack) {
|
||||||
while stack.program_counter < (stack.program.len() as u16) {
|
while stack.program_counter < (stack.program.len() as u16) {
|
||||||
@ -11,7 +11,7 @@ fn find_labels(stack: &mut Stack) {
|
|||||||
|
|
||||||
if stack.labels[label.data as usize].is_some() {
|
if stack.labels[label.data as usize].is_some() {
|
||||||
eprintln!("Label {} already defined", label.data);
|
eprintln!("Label {} already defined", label.data);
|
||||||
return;
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if label.data == 0 {
|
if label.data == 0 {
|
||||||
@ -22,23 +22,18 @@ fn find_labels(stack: &mut Stack) {
|
|||||||
stack.labels[label.data as usize] = Some(stack.program_counter as i16);
|
stack.labels[label.data as usize] = Some(stack.program_counter as i16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if stack.labels[0].is_some() {
|
stack.program_counter = stack.labels[0].unwrap_or(0) as u16;
|
||||||
stack.program_counter = stack.labels[0].unwrap() as u16;
|
|
||||||
} else {
|
|
||||||
stack.program_counter = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_prefix_operators(instruction: &mut Instruction, memory: &mut Vec<u16>) {
|
fn find_prefix_operators(instruction: &mut Instruction, memory: &mut StackVec) {
|
||||||
match instruction.name.chars().nth(0) {
|
match instruction.name.chars().nth(0) {
|
||||||
Some('|') => {
|
Some('|') => {
|
||||||
instruction.name = instruction.name.chars().skip(1).collect();
|
instruction.name = instruction.name.chars().skip(1).collect();
|
||||||
|
instruction.data = memory.pop();
|
||||||
instruction.data = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
|
||||||
},
|
},
|
||||||
Some('^') => {
|
Some('^') => {
|
||||||
instruction.name = instruction.name.chars().skip(1).collect();
|
instruction.name = instruction.name.chars().skip(1).collect();
|
||||||
//dbg!(&instruction);
|
|
||||||
if instruction.name.chars().nth(0) != Some('#') {
|
if instruction.name.chars().nth(0) != Some('#') {
|
||||||
println!("{0} {1}", instruction.name, instruction.data.to_string());
|
println!("{0} {1}", instruction.name, instruction.data.to_string());
|
||||||
} else if instruction.arg.is_empty() {
|
} else if instruction.arg.is_empty() {
|
||||||
@ -51,7 +46,7 @@ fn find_prefix_operators(instruction: &mut Instruction, memory: &mut Vec<u16>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name: &String) {
|
pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name: String) {
|
||||||
find_labels(stack);
|
find_labels(stack);
|
||||||
|
|
||||||
while let Some(mut instruction) = stack.program.get_mut(stack.program_counter as usize) {
|
while let Some(mut instruction) = stack.program.get_mut(stack.program_counter as usize) {
|
||||||
@ -65,11 +60,11 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
|
|||||||
|
|
||||||
match instruction.name.as_str() {
|
match instruction.name.as_str() {
|
||||||
// Stack operations
|
// Stack operations
|
||||||
"push" => instructions::push::push(&mut stack.memory, &instruction.data),
|
"push" => instructions::push::push(&mut stack.memory, instruction.data),
|
||||||
"pop" => instructions::pop::pop(&mut stack.memory),
|
"pop" => instructions::pop::pop(&mut stack.memory),
|
||||||
"dup" => instructions::dup::dup(&mut stack.memory),
|
"dup" => instructions::dup::dup(&mut stack.memory),
|
||||||
"swap" => instructions::swap::swap(&mut stack.memory),
|
"swap" => instructions::swap::swap(&mut stack.memory),
|
||||||
"pick" => instructions::pick::pick(&mut stack.memory, &instruction.data),
|
"pick" => instructions::pick::pick(&mut stack.memory, instruction.data),
|
||||||
|
|
||||||
// Math
|
// Math
|
||||||
"add" => instructions::add::add(&mut stack.memory),
|
"add" => instructions::add::add(&mut stack.memory),
|
||||||
@ -93,46 +88,45 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
|
|||||||
"bnot" => instructions::not::not(&mut stack.memory),
|
"bnot" => instructions::not::not(&mut stack.memory),
|
||||||
|
|
||||||
// Labels
|
// Labels
|
||||||
"jmp" => instructions::jmp::jmp(&mut stack.labels, &mut stack.program_counter, &instruction.data),
|
"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),
|
"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),
|
"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),
|
"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),
|
"kjz" => instructions::kjz::kjz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
||||||
|
|
||||||
// Input/Output
|
// Input/Output
|
||||||
"putc" => instructions::putc::putc(&mut stack.memory),
|
"putc" => instructions::putc::putc(&mut stack.memory),
|
||||||
"getc" => instructions::getc::getc(&mut stack.memory),
|
"getc" => instructions::getc::getc(&mut stack.memory),
|
||||||
"scan" => instructions::scan::scan(&mut stack.memory),
|
"scan" => instructions::scan::scan(&mut stack.memory),
|
||||||
"meow" => instructions::meow::meow(&mut stack.memory),
|
"meow" => instructions::meow::meow(&mut stack.memory),
|
||||||
"#print" => instructions::print::print(&instruction.arg),
|
"#print" => instructions::print::print(instruction.arg.clone()),
|
||||||
"$print" => instructions::print::print(&instruction.arg),
|
"$print" => instructions::print::print(instruction.arg.clone()),
|
||||||
"#println" => instructions::println::println(&instruction.arg),
|
"#println" => instructions::println::println(instruction.arg.clone()),
|
||||||
"$println" => instructions::println::println(&instruction.arg),
|
"$println" => instructions::println::println(instruction.arg.clone()),
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
"args" => instructions::args::args(&mut stack.memory, &mut origin_stack, &instruction.data),
|
"args" => instructions::args::args(&mut stack.memory, &mut origin_stack, instruction.data),
|
||||||
"#exec" => {
|
"#exec" => {
|
||||||
let arg = instruction.arg.clone();
|
let arg = instruction.arg.clone();
|
||||||
instructions::exec::exec(stack, &arg, &mod_name);
|
instructions::exec::exec(stack, arg, mod_name.clone())
|
||||||
}
|
},
|
||||||
|
|
||||||
// Self-modifying
|
// Self-modifying
|
||||||
|
|
||||||
"#insert" => {
|
"#insert" => {
|
||||||
let arg = instruction.arg.clone();
|
let arg = instruction.arg.clone();
|
||||||
let data = instruction.data.clone();
|
let data = instruction.data.clone();
|
||||||
|
instructions::insert::insert(&mut stack.program, arg, data)
|
||||||
instructions::insert::insert(&mut stack.program, &arg, &data)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
"dump" => instructions::dump::dump(&mut stack.memory),
|
"dump" => instructions::dump::dump(&mut stack.memory),
|
||||||
"size" => instructions::size::size(&mut stack.memory),
|
"size" => instructions::size::size(&mut stack.memory),
|
||||||
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
||||||
"#expr" => instructions::expr::expr(&mut stack.memory, &instruction.arg),
|
"#expr" => instructions::expr::expr(&mut stack.memory, instruction.arg.clone()),
|
||||||
"nop" => continue,
|
"nop" => continue,
|
||||||
"quit" => break,
|
"quit" => break,
|
||||||
"exit" => instructions::exit::exit(&instruction.data),
|
"exit" => instructions::exit::exit(instruction.data),
|
||||||
|
|
||||||
// Platform-specific
|
// Platform-specific
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use crate::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
pub fn _unix_random(memory: &mut Vec<u16>) {
|
pub fn _unix_random(memory: &mut StackVec) {
|
||||||
let mut rng = File::open("/dev/urandom").unwrap();
|
let mut rng = File::open("/dev/urandom").unwrap();
|
||||||
|
|
||||||
let mut buffer = [0u8; 2];
|
let mut buffer = [0u8; 2];
|
||||||
rng.read_exact(&mut buffer).unwrap();
|
rng.read_exact(&mut buffer).unwrap();
|
||||||
|
|
||||||
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let data = memory.pop();
|
||||||
memory.push((u16::from_ne_bytes(buffer)) % (*data - 1));
|
memory.push((u16::from_ne_bytes(buffer)) % (data - 1));
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn add(memory: &mut Vec<u16>) {
|
pub fn add(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(a + b);
|
memory.push(a + b);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn and(memory: &mut Vec<u16>) {
|
pub fn and(memory: &mut StackVec) {
|
||||||
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let a: bool = memory.pop() == 1;
|
||||||
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let b: bool = memory.pop() == 1;
|
||||||
|
|
||||||
let c: u16 = if a && b {
|
let c: u16 = if a && b {
|
||||||
1
|
1
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
use crate::{errors::RunError, stack::Stack};
|
use crate::{errors::RunError, stack::{Stack, StackVec}};
|
||||||
|
|
||||||
pub fn args(memory: &mut Vec<u16>, origin_stack: &mut Option<&mut Stack>, data: &u16) {
|
pub fn args(memory: &mut StackVec, origin_stack: &mut Option<&mut Stack>, data: u16) {
|
||||||
if let Some(origin_stack) = origin_stack.as_mut() {
|
if let Some(origin_stack) = origin_stack.as_mut() {
|
||||||
let mut data = *data;
|
let mut data = data;
|
||||||
|
|
||||||
if data == 0 {
|
if data == 0 {
|
||||||
data = origin_stack.memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
data = origin_stack.memory.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..data {
|
for _ in 0..data {
|
||||||
memory.push(origin_stack.memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
|
memory.push(origin_stack.memory.pop());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{}", RunError::RequestArgsInMainModule);
|
eprintln!("{}", RunError::RequestArgsInMainModule);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn band(memory: &mut Vec<u16>) {
|
pub fn band(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(a & b);
|
memory.push(a & b);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn bnand(memory: &mut Vec<u16>) {
|
pub fn bnand(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(!(a & b));
|
memory.push(!(a & b));
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn bor(memory: &mut Vec<u16>) {
|
pub fn bor(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(a | b);
|
memory.push(a | b);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn bxor(memory: &mut Vec<u16>) {
|
pub fn bxor(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(a ^ b);
|
memory.push(a ^ b);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn div(memory: &mut Vec<u16>) {
|
pub fn div(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(b / a);
|
memory.push(b / a);
|
||||||
}
|
}
|
@ -1,4 +1,6 @@
|
|||||||
pub fn dump(memory: &mut Vec<u16>) {
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn dump(memory: &mut StackVec) {
|
||||||
if memory.is_empty() {
|
if memory.is_empty() {
|
||||||
println!("Stack is empty.");
|
println!("Stack is empty.");
|
||||||
return;
|
return;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn dup(memory: &mut Vec<u16>) {
|
pub fn dup(memory: &mut StackVec) {
|
||||||
memory.push(*memory.last().expect(&format!("{}", RunError::MemoryEmpty)));
|
let data = memory.last();
|
||||||
|
memory.push(data);
|
||||||
}
|
}
|
@ -1,19 +1,19 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use crate::{parse, execute, Stack, errors::RunError};
|
use crate::{parse, execute, Stack, errors::RunError};
|
||||||
|
|
||||||
pub fn exec(mut stack: &mut Stack, arg: &String, mod_name: &String) {
|
pub fn exec(mut stack: &mut Stack, arg: String, mod_name: String) {
|
||||||
if mod_name == arg {
|
if mod_name == arg {
|
||||||
eprintln!("{}", RunError::ExecuteItself(arg.to_string()));
|
eprintln!("{}", RunError::ExecuteItself(arg.to_string()));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lines = fs::read_to_string(&arg).expect(&format!("{}", RunError::FailToReadFile));
|
let lines = fs::read_to_string(&arg).expect(&format!("{}", RunError::FailToReadFile));
|
||||||
let mut temp_stack = Stack::new();
|
let mut temp_stack = Stack::new(stack.memory.size());
|
||||||
|
|
||||||
parse(&mut temp_stack, &lines);
|
parse(&mut temp_stack, &lines);
|
||||||
execute(&mut temp_stack, Some(&mut stack), &arg.clone());
|
execute(&mut temp_stack, Some(&mut stack), arg.clone());
|
||||||
|
|
||||||
for item in temp_stack.memory {
|
for item in temp_stack.memory.iter() {
|
||||||
stack.memory.push(item);
|
stack.memory.push(*item);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
pub fn exit(data: &u16) {
|
pub fn exit(data: u16) {
|
||||||
std::process::exit((*data).into());
|
std::process::exit(data as i32);
|
||||||
}
|
}
|
@ -1,24 +1,27 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn expr(memory: &mut Vec<u16>, arg: &String) {
|
pub fn expr(memory: &mut StackVec, arg: String) {
|
||||||
for code in arg.chars() {
|
for code in arg.chars() {
|
||||||
match code {
|
match code {
|
||||||
'>' => memory.push(0),
|
'>' => memory.push(0),
|
||||||
'$' => { memory.pop(); },
|
'$' => { memory.pop(); },
|
||||||
':' => memory.push(*memory.last().expect(&format!("{}", RunError::MemoryEmpty))),
|
':' => {
|
||||||
|
let data = memory.last().clone();
|
||||||
|
memory.push(data);
|
||||||
|
},
|
||||||
'\\' => {
|
'\\' => {
|
||||||
let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let ax = memory.pop();
|
||||||
let ax2 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let ax2 = memory.pop();
|
||||||
|
|
||||||
memory.push(ax);
|
memory.push(ax);
|
||||||
memory.push(ax2);
|
memory.push(ax2);
|
||||||
}
|
}
|
||||||
'+' => {
|
'+' => {
|
||||||
let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let ax = memory.pop();
|
||||||
memory.push(ax + 1);
|
memory.push(ax + 1);
|
||||||
}
|
}
|
||||||
'-' => {
|
'-' => {
|
||||||
let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let ax = memory.pop();
|
||||||
memory.push(ax - 1);
|
memory.push(ax - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn getc(memory: &mut Vec<u16>) {
|
pub fn getc(memory: &mut StackVec) {
|
||||||
let char = std::io::stdin()
|
let char = std::io::stdin()
|
||||||
.bytes()
|
.bytes()
|
||||||
.next()
|
.next()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{errors::RunError, stack::Instruction};
|
use crate::{errors::RunError, stack::Instruction};
|
||||||
|
|
||||||
pub fn insert(program: &mut Vec<Instruction>, arg: &String, data: &u16) {
|
pub fn insert(program: &mut Vec<Instruction>, arg: String, data: u16) {
|
||||||
let args: Vec<char> = arg.chars().collect();
|
let args: Vec<char> = arg.chars().collect();
|
||||||
|
|
||||||
if args[0] == '#' || args[0] == '$' {
|
if args[0] == '#' || args[0] == '$' {
|
||||||
@ -21,6 +21,6 @@ pub fn insert(program: &mut Vec<Instruction>, arg: &String, data: &u16) {
|
|||||||
program.push(Instruction {
|
program.push(Instruction {
|
||||||
name: arg.to_string(),
|
name: arg.to_string(),
|
||||||
arg: "\n".to_string(),
|
arg: "\n".to_string(),
|
||||||
data: *data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
use crate::errors::RunError;
|
use crate::errors::RunError;
|
||||||
|
|
||||||
pub fn jmp(labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
|
pub fn jmp(labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
|
||||||
if labels[*data as usize].is_none() {
|
if labels[data as usize].is_none() {
|
||||||
eprintln!("{}", RunError::UnknownLabel(*data));
|
eprintln!("{}", RunError::UnknownLabel(data));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
*program_counter = (labels[*data as usize].unwrap() - 1) as u16;
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn jnz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
|
pub fn jnz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
|
||||||
if labels[*data as usize].is_none() {
|
if labels[data as usize].is_none() {
|
||||||
eprintln!("{}", RunError::UnknownLabel(*data));
|
eprintln!("{}", RunError::UnknownLabel(data));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if memory.pop() != Some(0) {
|
if memory.pop() != 0 {
|
||||||
*program_counter = (labels[*data as usize].unwrap() - 1) as u16;
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn jz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
|
pub fn jz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
|
||||||
if labels[*data as usize].is_none() {
|
if labels[data as usize].is_none() {
|
||||||
eprintln!("{}", RunError::UnknownLabel(*data));
|
eprintln!("{}", RunError::UnknownLabel(data));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if memory.pop() == Some(0) {
|
if memory.pop() == 0 {
|
||||||
*program_counter = (labels[*data as usize].unwrap() - 1) as u16;
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn kjnz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
|
pub fn kjnz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
|
||||||
if labels[*data as usize].is_none() {
|
if labels[data as usize].is_none() {
|
||||||
eprintln!("{}", RunError::UnknownLabel(*data));
|
eprintln!("{}", RunError::UnknownLabel(data));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if memory.last() != Some(&0) {
|
if memory.last() != 0 {
|
||||||
*program_counter = (labels[*data as usize].unwrap() - 1) as u16;
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn kjz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
|
pub fn kjz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
|
||||||
if labels[*data as usize].is_none() {
|
if labels[data as usize].is_none() {
|
||||||
eprintln!("{}", RunError::UnknownLabel(*data));
|
eprintln!("{}", RunError::UnknownLabel(data));
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if memory.last() == Some(&0) {
|
if memory.last() == 0 {
|
||||||
*program_counter = (labels[*data as usize].unwrap() - 1) as u16;
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
pub fn maxsize(memory: &mut Vec<u16>) {
|
use crate::stack::StackVec;
|
||||||
memory.push(u16::MAX);
|
|
||||||
|
pub fn maxsize(memory: &mut StackVec) {
|
||||||
|
memory.push(memory.size() as u16);
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn meow(memory: &mut Vec<u16>) {
|
pub fn meow(memory: &mut StackVec) {
|
||||||
println!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
|
println!("{}", memory.pop());
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn modulo(memory: &mut Vec<u16>) {
|
pub fn modulo(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(b % a);
|
memory.push(b % a);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn mul(memory: &mut Vec<u16>) {
|
pub fn mul(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(b * a);
|
memory.push(b * a);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn nand(memory: &mut Vec<u16>) {
|
pub fn nand(memory: &mut StackVec) {
|
||||||
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let a: bool = memory.pop() == 1;
|
||||||
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let b: bool = memory.pop() == 1;
|
||||||
|
|
||||||
let c: u16 = if !(a && b) {
|
let c: u16 = if !(a && b) {
|
||||||
1
|
1
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn not(memory: &mut Vec<u16>) {
|
pub fn not(memory: &mut StackVec) {
|
||||||
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let a: bool = memory.pop() == 1;
|
||||||
|
|
||||||
let c: u16 = if !a {
|
let c: u16 = if !a {
|
||||||
1
|
1
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn or(memory: &mut Vec<u16>) {
|
pub fn or(memory: &mut StackVec) {
|
||||||
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let a: bool = memory.pop() == 1;
|
||||||
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let b: bool = memory.pop() == 1;
|
||||||
|
|
||||||
let c: u16 = if a || b {
|
let c: u16 = if a || b {
|
||||||
1
|
1
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn pick(memory: &mut Vec<u16>, data: &u16) {
|
pub fn pick(memory: &mut StackVec, data: u16) {
|
||||||
if *data > memory.len() as u16 {
|
if data > memory.len() as u16 {
|
||||||
eprintln!("{}", RunError::PickTooDeep);
|
eprintln!("{}", RunError::PickTooDeep);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let arg = memory.pop();
|
||||||
memory.push(*memory.get(memory.len() - (arg as usize) - 1).expect(&format!("{}", RunError::PickOutOfBounds)));
|
memory.push(*memory.get(memory.len() - (arg as usize) - 1).expect(&format!("{}", RunError::PickOutOfBounds)));
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
pub fn pop(memory: &mut Vec<u16>) {
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn pop(memory: &mut StackVec) {
|
||||||
memory.pop();
|
memory.pop();
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
pub fn print(arg: &String) {
|
pub fn print(arg: String) {
|
||||||
print!("{}", arg);
|
print!("{}", arg);
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
pub fn println(arg: &String) {
|
pub fn println(arg: String) {
|
||||||
println!("{}", arg);
|
println!("{}", arg);
|
||||||
}
|
}
|
@ -1,3 +1,5 @@
|
|||||||
pub fn push(memory: &mut Vec<u16>, data: &u16) {
|
use crate::stack::StackVec;
|
||||||
memory.push(*data);
|
|
||||||
|
pub fn push(memory: &mut StackVec, data: u16) {
|
||||||
|
memory.push(data);
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn putc(memory: &mut Vec<u16>) {
|
pub fn putc(memory: &mut StackVec) {
|
||||||
print!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) as u8 as char);
|
print!("{}", memory.pop() as u8 as char);
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use fastrand;
|
use fastrand;
|
||||||
use crate::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn random(memory: &mut Vec<u16>) {
|
pub fn random(memory: &mut StackVec) {
|
||||||
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let data = memory.pop();
|
||||||
memory.push(fastrand::u16(..) % (*data - 1));
|
memory.push(fastrand::u16(..) % (data - 1));
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use crate::errors::RunError;
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn scan(memory: &mut Vec<u16>) {
|
pub fn scan(memory: &mut StackVec) {
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
|
|
||||||
std::io::stdin().read_line(&mut input).expect(&format!("{}", RunError::FailToReadLineFromConsole));
|
std::io::stdin().read_line(&mut input).expect(&format!("{}", RunError::FailToReadLineFromConsole));
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
pub fn size(memory: &mut Vec<u16>) {
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn size(memory: &mut StackVec) {
|
||||||
memory.push(memory.len() as u16);
|
memory.push(memory.len() as u16);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn sub(memory: &mut Vec<u16>) {
|
pub fn sub(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(b - a);
|
memory.push(b - a);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn swap(memory: &mut Vec<u16>) {
|
pub fn swap(memory: &mut StackVec) {
|
||||||
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let a: u16 = memory.pop();
|
||||||
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
memory.push(a);
|
memory.push(a);
|
||||||
memory.push(b);
|
memory.push(b);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::errors::RunError;
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
pub fn xor(memory: &mut Vec<u16>) {
|
pub fn xor(memory: &mut StackVec) {
|
||||||
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let a: bool = memory.pop() == 1;
|
||||||
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
let b: bool = memory.pop() == 1;
|
||||||
|
|
||||||
let c: u16 = if !a != !b {
|
let c: u16 = if !a != !b {
|
||||||
1
|
1
|
||||||
|
22
src/main.rs
22
src/main.rs
@ -17,6 +17,7 @@ labast - Labaski interpreter written in Rust.
|
|||||||
usage: labast [options] [ file.lb ]
|
usage: labast [options] [ file.lb ]
|
||||||
|
|
||||||
options:
|
options:
|
||||||
|
--stack-size sets stack max size (default: 256)
|
||||||
-h, --help prints help information
|
-h, --help prints help information
|
||||||
-v, --version prints version
|
-v, --version prints version
|
||||||
";
|
";
|
||||||
@ -30,7 +31,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new(args.stack_size);
|
||||||
|
|
||||||
if args.input.is_none() {
|
if args.input.is_none() {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
@ -46,21 +47,22 @@ fn main() {
|
|||||||
|
|
||||||
stdin.lock().read_line(&mut line).unwrap();
|
stdin.lock().read_line(&mut line).unwrap();
|
||||||
|
|
||||||
parse(&mut stack, &line.trim());
|
parse(&mut stack, line.trim());
|
||||||
execute(&mut stack, None, &"inline".to_string());
|
execute(&mut stack, None, "inline".to_string());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let input = &args.input.expect("error: no input file");
|
let input = &args.input.expect("error: no input file");
|
||||||
let lines = fs::read_to_string(&input).expect(&format!("{}", RunError::FailToReadFile));
|
let lines = fs::read_to_string(&input).expect(&format!("{}", RunError::FailToReadFile));
|
||||||
|
|
||||||
parse(&mut stack, &lines);
|
parse(&mut stack, &lines);
|
||||||
execute(&mut stack, None, &String::from(input.file_name().expect("Failed to read file name.").to_str().expect("Failed to convert file name to string")));
|
execute(&mut stack, None, String::from(input.file_name().expect("Failed to read file name.").to_str().expect("Failed to convert file name to string")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct AppArgs {
|
struct AppArgs {
|
||||||
input: Option<std::path::PathBuf>,
|
input: Option<std::path::PathBuf>,
|
||||||
|
stack_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
||||||
@ -77,6 +79,7 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let args = AppArgs {
|
let args = AppArgs {
|
||||||
|
stack_size: pargs.opt_value_from_fn("--stack-size", parse_stack_size)?.unwrap_or(256),
|
||||||
input: pargs.opt_free_from_str()?,
|
input: pargs.opt_free_from_str()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,3 +90,14 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
|||||||
|
|
||||||
return Ok(args);
|
return Ok(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_stack_size(s: &str) -> Result<usize, &'static str> {
|
||||||
|
let number = s.parse().map_err(|_| "Argument for stack size is not a number");
|
||||||
|
|
||||||
|
if number > Ok(u16::MAX) {
|
||||||
|
eprintln!("Stack size cannot be more than 65535");
|
||||||
|
std::process::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(number?.into())
|
||||||
|
}
|
53
src/stack.rs
53
src/stack.rs
@ -1,3 +1,7 @@
|
|||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::errors::StackError;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -5,21 +9,62 @@ pub struct Instruction {
|
|||||||
pub data: u16
|
pub data: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
pub program: Vec<Instruction>,
|
pub program: Vec<Instruction>,
|
||||||
pub program_counter: u16,
|
pub program_counter: u16,
|
||||||
pub labels: [Option<i16>; 256],
|
pub labels: [Option<i16>; 256],
|
||||||
pub memory: Vec<u16>
|
pub memory: StackVec
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
pub fn new() -> Stack {
|
pub fn new(stack_size: usize) -> Stack {
|
||||||
return Stack {
|
return Stack {
|
||||||
program: Vec::new(),
|
program: Vec::new(),
|
||||||
program_counter: 0,
|
program_counter: 0,
|
||||||
labels: [None; 256],
|
labels: [None; 256],
|
||||||
memory: Vec::new()
|
memory: StackVec::new(stack_size)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct StackVec {
|
||||||
|
data: Vec<u16>,
|
||||||
|
max_size: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackVec {
|
||||||
|
fn new(max_size: usize) -> Self {
|
||||||
|
StackVec {
|
||||||
|
data: Vec::new(),
|
||||||
|
max_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> usize {
|
||||||
|
self.max_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, item: u16) {
|
||||||
|
if self.data.len() + 1 > self.max_size {
|
||||||
|
panic!("{}", StackError::StackOverflow);
|
||||||
|
} else {
|
||||||
|
self.data.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop(&mut self) -> u16 {
|
||||||
|
self.data.pop().expect(&format!("{}", StackError::StackUnderflow))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn last(&mut self) -> u16 {
|
||||||
|
*self.data.last().expect(&format!("{}", StackError::StackUnderflow))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for StackVec {
|
||||||
|
type Target = Vec<u16>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user