обновление 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
 | 
			
		||||
/archive
 | 
			
		||||
/bin
 | 
			
		||||
							
								
								
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -10,7 +10,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "labast"
 | 
			
		||||
version = "1.0.4"
 | 
			
		||||
version = "1.0.5"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "fastrand",
 | 
			
		||||
 "pico-args",
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "labast"
 | 
			
		||||
version = "1.0.4"
 | 
			
		||||
version = "1.0.5"
 | 
			
		||||
authors = [ "n3tael" ]
 | 
			
		||||
edition = "2021"
 | 
			
		||||
description = "A zero-dependencies Labaski interpreter written in Rust."
 | 
			
		||||
description = "A Labaski interpreter written in Rust."
 | 
			
		||||
readme = "README.md"
 | 
			
		||||
license = "MIT"
 | 
			
		||||
publish = false
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,9 @@ echo Building for Windows...
 | 
			
		||||
cargo build --release
 | 
			
		||||
echo Building for Linux...
 | 
			
		||||
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\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!
 | 
			
		||||
@ -12,7 +12,7 @@
 | 
			
		||||
 | 
			
		||||
@ 2
 | 
			
		||||
    sub
 | 
			
		||||
    meow dkdkd
 | 
			
		||||
    meow
 | 
			
		||||
    quit 
 | 
			
		||||
 | 
			
		||||
@ 3
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,19 @@
 | 
			
		||||
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 {
 | 
			
		||||
    RequestArgsInMainModule,
 | 
			
		||||
    ExecuteItself(String),
 | 
			
		||||
@ -11,7 +25,6 @@ pub enum RunError {
 | 
			
		||||
    FailToReadLineFromConsole,
 | 
			
		||||
    UnknownLabel(u16),
 | 
			
		||||
    InvalidExpressionUnknownOperator(String),
 | 
			
		||||
    MemoryEmpty,
 | 
			
		||||
    AttemptToInsertHashOrStringInst,
 | 
			
		||||
    AttemptToInsertEmptyConst,
 | 
			
		||||
    AttemptToInsertALabel
 | 
			
		||||
@ -30,7 +43,6 @@ impl Display for RunError {
 | 
			
		||||
            RunError::FailToReadLineFromConsole => write!(f, "Failed to read line from console"),
 | 
			
		||||
            RunError::UnknownLabel(label_name) => write!(f, "Unknown label: {}", label_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::AttemptToInsertEmptyConst => write!(f, "Attempt to insert an empty constant"),
 | 
			
		||||
            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) {
 | 
			
		||||
    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() {
 | 
			
		||||
            eprintln!("Label {} already defined", label.data);
 | 
			
		||||
            return;
 | 
			
		||||
            std::process::exit(2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if stack.labels[0].is_some() {
 | 
			
		||||
        stack.program_counter = stack.labels[0].unwrap() as u16;
 | 
			
		||||
    } else {
 | 
			
		||||
        stack.program_counter = 0;
 | 
			
		||||
    }
 | 
			
		||||
    stack.program_counter = stack.labels[0].unwrap_or(0) as u16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        Some('|') => {
 | 
			
		||||
            instruction.name = instruction.name.chars().skip(1).collect();
 | 
			
		||||
 | 
			
		||||
            instruction.data = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
            instruction.data = memory.pop();
 | 
			
		||||
        },
 | 
			
		||||
        Some('^') => {
 | 
			
		||||
            instruction.name = instruction.name.chars().skip(1).collect();
 | 
			
		||||
            //dbg!(&instruction);
 | 
			
		||||
 | 
			
		||||
            if instruction.name.chars().nth(0) != Some('#') {
 | 
			
		||||
                println!("{0} {1}", instruction.name, instruction.data.to_string());
 | 
			
		||||
            } 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);
 | 
			
		||||
 | 
			
		||||
    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() {
 | 
			
		||||
            // 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),
 | 
			
		||||
            "dup"  => instructions::dup::dup(&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
 | 
			
		||||
            "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),
 | 
			
		||||
 | 
			
		||||
            // 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),
 | 
			
		||||
            "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),
 | 
			
		||||
            "$print"   => instructions::print::print(&instruction.arg),
 | 
			
		||||
            "#println" => instructions::println::println(&instruction.arg),
 | 
			
		||||
            "$println" => instructions::println::println(&instruction.arg),
 | 
			
		||||
            "#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),
 | 
			
		||||
            "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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
                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)
 | 
			
		||||
                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),
 | 
			
		||||
            "#expr"   => instructions::expr::expr(&mut stack.memory, instruction.arg.clone()),
 | 
			
		||||
            "nop"     => continue,
 | 
			
		||||
            "quit"    => break,
 | 
			
		||||
            "exit"    => instructions::exit::exit(&instruction.data),
 | 
			
		||||
            "exit"    => instructions::exit::exit(instruction.data),
 | 
			
		||||
 | 
			
		||||
            // Platform-specific
 | 
			
		||||
            #[cfg(target_family = "unix")] 
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,14 @@
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
use crate::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
#[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 buffer = [0u8; 2];
 | 
			
		||||
    rng.read_exact(&mut buffer).unwrap();
 | 
			
		||||
 | 
			
		||||
    let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    memory.push((u16::from_ne_bytes(buffer)) % (*data - 1));
 | 
			
		||||
    let data = memory.pop();
 | 
			
		||||
    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>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn add(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(a + b);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn and(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
    let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
pub fn and(memory: &mut StackVec) {
 | 
			
		||||
    let a: bool = memory.pop() == 1;
 | 
			
		||||
    let b: bool = memory.pop() == 1;
 | 
			
		||||
 | 
			
		||||
    let c: u16 = if a && b {
 | 
			
		||||
        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() {
 | 
			
		||||
        let mut data = *data;
 | 
			
		||||
        let mut data = data;
 | 
			
		||||
 | 
			
		||||
        if data == 0 {
 | 
			
		||||
            data = origin_stack.memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
            data = origin_stack.memory.pop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for _ in 0..data {
 | 
			
		||||
            memory.push(origin_stack.memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
            memory.push(origin_stack.memory.pop());
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        eprintln!("{}", RunError::RequestArgsInMainModule);
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn band(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn band(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(a & b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn bnand(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn bnand(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(!(a & b));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn bor(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn bor(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(a | b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn bxor(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn bxor(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(a ^ b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn div(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn div(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    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() {
 | 
			
		||||
        println!("Stack is empty.");
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn dup(memory: &mut Vec<u16>) {
 | 
			
		||||
    memory.push(*memory.last().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
pub fn dup(memory: &mut StackVec) {
 | 
			
		||||
    let data = memory.last();
 | 
			
		||||
    memory.push(data);
 | 
			
		||||
}
 | 
			
		||||
@ -1,19 +1,19 @@
 | 
			
		||||
use std::fs;
 | 
			
		||||
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 {
 | 
			
		||||
        eprintln!("{}", RunError::ExecuteItself(arg.to_string()));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    execute(&mut temp_stack, Some(&mut stack), &arg.clone());
 | 
			
		||||
    execute(&mut temp_stack, Some(&mut stack), arg.clone());
 | 
			
		||||
 | 
			
		||||
    for item in temp_stack.memory {
 | 
			
		||||
        stack.memory.push(item);
 | 
			
		||||
    for item in temp_stack.memory.iter() {
 | 
			
		||||
        stack.memory.push(*item);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
pub fn exit(data: &u16) {
 | 
			
		||||
    std::process::exit((*data).into());
 | 
			
		||||
pub fn exit(data: u16) {
 | 
			
		||||
    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() {
 | 
			
		||||
        match code {
 | 
			
		||||
            '>' => memory.push(0),
 | 
			
		||||
            '$' => { 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 ax2 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                let ax = memory.pop();
 | 
			
		||||
                let ax2 = memory.pop();
 | 
			
		||||
                
 | 
			
		||||
                memory.push(ax);
 | 
			
		||||
                memory.push(ax2);
 | 
			
		||||
            }
 | 
			
		||||
            '+' => {
 | 
			
		||||
                let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                let ax = memory.pop();
 | 
			
		||||
                memory.push(ax + 1);
 | 
			
		||||
            }
 | 
			
		||||
            '-' => {
 | 
			
		||||
                let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                let ax = memory.pop();
 | 
			
		||||
                memory.push(ax - 1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
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()
 | 
			
		||||
        .bytes()
 | 
			
		||||
        .next()
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
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();
 | 
			
		||||
    
 | 
			
		||||
    if args[0] == '#' || args[0] == '$' {
 | 
			
		||||
@ -21,6 +21,6 @@ pub fn insert(program: &mut Vec<Instruction>, arg: &String, data: &u16) {
 | 
			
		||||
    program.push(Instruction {
 | 
			
		||||
        name:  arg.to_string(),
 | 
			
		||||
        arg:  "\n".to_string(),
 | 
			
		||||
        data: *data
 | 
			
		||||
        data
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn jmp(labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
pub fn jmp(labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
 | 
			
		||||
    if labels[data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(data));
 | 
			
		||||
        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) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
pub fn jnz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
 | 
			
		||||
    if labels[data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.pop() != Some(0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    if memory.pop() != 0 {
 | 
			
		||||
        *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) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
pub fn jz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
 | 
			
		||||
    if labels[data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.pop() == Some(0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    if memory.pop() == 0 {
 | 
			
		||||
        *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) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
pub fn kjnz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
 | 
			
		||||
    if labels[data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.last() != Some(&0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    if memory.last() != 0 {
 | 
			
		||||
        *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) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
pub fn kjz(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: u16) {
 | 
			
		||||
    if labels[data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.last() == Some(&0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    if memory.last() == 0 {
 | 
			
		||||
        *program_counter = (labels[data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
pub fn maxsize(memory: &mut Vec<u16>) {
 | 
			
		||||
    memory.push(u16::MAX);
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
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>) {
 | 
			
		||||
    println!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
pub fn meow(memory: &mut StackVec) {
 | 
			
		||||
    println!("{}", memory.pop());
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn modulo(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn modulo(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(b % a);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn mul(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn mul(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(b * a);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn nand(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
    let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
pub fn nand(memory: &mut StackVec) {
 | 
			
		||||
    let a: bool = memory.pop() == 1;
 | 
			
		||||
    let b: bool = memory.pop() == 1;
 | 
			
		||||
 | 
			
		||||
    let c: u16 = if !(a && b) {
 | 
			
		||||
        1
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn not(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
pub fn not(memory: &mut StackVec) {
 | 
			
		||||
    let a: bool = memory.pop() == 1;
 | 
			
		||||
    
 | 
			
		||||
    let c: u16 = if !a {
 | 
			
		||||
        1
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn or(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
    let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
pub fn or(memory: &mut StackVec) {
 | 
			
		||||
    let a: bool = memory.pop() == 1;
 | 
			
		||||
    let b: bool = memory.pop() == 1;
 | 
			
		||||
 | 
			
		||||
    let c: u16 = if a || b {
 | 
			
		||||
        1
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::{errors::RunError, stack::StackVec};
 | 
			
		||||
 | 
			
		||||
pub fn pick(memory: &mut Vec<u16>, data: &u16) {
 | 
			
		||||
    if *data > memory.len() as u16 {
 | 
			
		||||
pub fn pick(memory: &mut StackVec, data: u16) {
 | 
			
		||||
    if data > memory.len() as u16 {
 | 
			
		||||
        eprintln!("{}", RunError::PickTooDeep);
 | 
			
		||||
        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)));
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
pub fn pop(memory: &mut Vec<u16>) {
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn pop(memory: &mut StackVec) {
 | 
			
		||||
    memory.pop();
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
pub fn print(arg: &String) {
 | 
			
		||||
pub fn print(arg: String) {
 | 
			
		||||
    print!("{}", arg);
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
pub fn println(arg: &String) {
 | 
			
		||||
pub fn println(arg: String) {
 | 
			
		||||
    println!("{}", arg);
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
pub fn push(memory: &mut Vec<u16>, data: &u16) {
 | 
			
		||||
    memory.push(*data);
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
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>) {
 | 
			
		||||
    print!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) as u8 as char);
 | 
			
		||||
pub fn putc(memory: &mut StackVec) {
 | 
			
		||||
    print!("{}", memory.pop() as u8 as char);
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
use fastrand;
 | 
			
		||||
use crate::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn random(memory: &mut Vec<u16>) {
 | 
			
		||||
    let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    memory.push(fastrand::u16(..) % (*data - 1));
 | 
			
		||||
pub fn random(memory: &mut StackVec) {
 | 
			
		||||
    let data = memory.pop();
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn sub(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn sub(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(b - a);
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn swap(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
pub fn swap(memory: &mut StackVec) {
 | 
			
		||||
    let a: u16 = memory.pop();
 | 
			
		||||
    let b: u16 = memory.pop();
 | 
			
		||||
 | 
			
		||||
    memory.push(a);
 | 
			
		||||
    memory.push(b);
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
use crate::stack::StackVec;
 | 
			
		||||
 | 
			
		||||
pub fn xor(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
    let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
 | 
			
		||||
pub fn xor(memory: &mut StackVec) {
 | 
			
		||||
    let a: bool = memory.pop() == 1;
 | 
			
		||||
    let b: bool = memory.pop() == 1;
 | 
			
		||||
 | 
			
		||||
    let c: u16 = if !a != !b {
 | 
			
		||||
        1
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/main.rs
									
									
									
									
									
								
							@ -17,6 +17,7 @@ labast - Labaski interpreter written in Rust.
 | 
			
		||||
usage: labast [options] [ file.lb ]
 | 
			
		||||
 | 
			
		||||
options:
 | 
			
		||||
  --stack-size          sets stack max size (default: 256)
 | 
			
		||||
  -h, --help            prints help information
 | 
			
		||||
  -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() {
 | 
			
		||||
        let mut line = String::new();
 | 
			
		||||
@ -46,21 +47,22 @@ fn main() {
 | 
			
		||||
 | 
			
		||||
            stdin.lock().read_line(&mut line).unwrap();
 | 
			
		||||
 | 
			
		||||
            parse(&mut stack, &line.trim());
 | 
			
		||||
            execute(&mut stack, None, &"inline".to_string());
 | 
			
		||||
            parse(&mut stack, line.trim());
 | 
			
		||||
            execute(&mut stack, None, "inline".to_string());
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        let input = &args.input.expect("error: no input file");
 | 
			
		||||
        let lines = fs::read_to_string(&input).expect(&format!("{}", RunError::FailToReadFile));
 | 
			
		||||
 | 
			
		||||
        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)]
 | 
			
		||||
struct AppArgs {
 | 
			
		||||
    input: Option<std::path::PathBuf>,
 | 
			
		||||
    stack_size: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_args() -> Result<AppArgs, pico_args::Error> {
 | 
			
		||||
@ -77,6 +79,7 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let args = AppArgs {
 | 
			
		||||
        stack_size: pargs.opt_value_from_fn("--stack-size", parse_stack_size)?.unwrap_or(256),
 | 
			
		||||
        input: pargs.opt_free_from_str()?,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -86,4 +89,15 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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)]
 | 
			
		||||
pub struct Instruction {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
@ -5,21 +9,62 @@ pub struct Instruction {
 | 
			
		||||
    pub data: u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Stack {
 | 
			
		||||
    pub program: Vec<Instruction>,
 | 
			
		||||
    pub program_counter: u16,
 | 
			
		||||
    pub labels: [Option<i16>; 256],
 | 
			
		||||
    pub memory: Vec<u16>
 | 
			
		||||
    pub memory: StackVec
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Stack {
 | 
			
		||||
    pub fn new() -> Stack {
 | 
			
		||||
    pub fn new(stack_size: usize) -> Stack {
 | 
			
		||||
        return Stack {
 | 
			
		||||
            program: Vec::new(),
 | 
			
		||||
            program_counter: 0,
 | 
			
		||||
            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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user