Compare commits
No commits in common. "master" and "v1.0.6" have entirely different histories.
83
Cargo.lock
generated
83
Cargo.lock
generated
@ -2,12 +2,6 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@ -19,88 +13,11 @@ name = "labast"
|
|||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"libloading",
|
|
||||||
"pico-args",
|
"pico-args",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libloading"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"windows-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pico-args"
|
name = "pico-args"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.48.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
||||||
|
@ -18,5 +18,4 @@ panic = "abort"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fastrand = "2.0.1"
|
fastrand = "2.0.1"
|
||||||
libloading = "0.8.1"
|
|
||||||
pico-args = "0.5.0"
|
pico-args = "0.5.0"
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
# Labast
|
# Labast
|
||||||
|
A Labaski interpreter written in Rust. Fully supports Labashki specs 1.12.
|
||||||
A Labaski interpreter written in Rust. Fully supports Labashki specs 1.15.1
|
|
@ -27,34 +27,23 @@ pub enum RunError {
|
|||||||
InvalidExpressionUnknownOperator(String),
|
InvalidExpressionUnknownOperator(String),
|
||||||
AttemptToInsertHashOrStringInst,
|
AttemptToInsertHashOrStringInst,
|
||||||
AttemptToInsertEmptyConst,
|
AttemptToInsertEmptyConst,
|
||||||
AttemptToInsertALabel,
|
AttemptToInsertALabel
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RunError {
|
impl Display for RunError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
RunError::RequestArgsInMainModule => {
|
RunError::RequestArgsInMainModule => write!(f, "Can't require arguments in the main module"),
|
||||||
write!(f, "Can't require arguments in the main module")
|
RunError::ExecuteItself(mod_name) => write!(f, "Module {}: Can't execute itself", mod_name),
|
||||||
}
|
|
||||||
RunError::ExecuteItself(mod_name) => {
|
|
||||||
write!(f, "Module {}: Can't execute itself", mod_name)
|
|
||||||
}
|
|
||||||
RunError::FailToReadFile => write!(f, "Unable to read file"),
|
RunError::FailToReadFile => write!(f, "Unable to read file"),
|
||||||
RunError::FailToGetCharFromConsole => write!(f, "Failed to get character from console"),
|
RunError::FailToGetCharFromConsole => write!(f, "Failed to get character from console"),
|
||||||
RunError::InvalidInputUShortInt => write!(
|
RunError::InvalidInputUShortInt => write!(f, "Invalid input. Please enter a valid unsigned short integer"),
|
||||||
f,
|
|
||||||
"Invalid input. Please enter a valid unsigned short integer"
|
|
||||||
),
|
|
||||||
RunError::PickTooDeep => write!(f, "Picking too deep"),
|
RunError::PickTooDeep => write!(f, "Picking too deep"),
|
||||||
RunError::PickOutOfBounds => write!(f, "Trying to get a value out of bounds"),
|
RunError::PickOutOfBounds => write!(f, "Trying to get a value out of bounds"),
|
||||||
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) => {
|
RunError::InvalidExpressionUnknownOperator(name) => write!(f, "Invalid expression: unknown operator '{}'", name),
|
||||||
write!(f, "Invalid expression: unknown operator '{}'", name)
|
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"),
|
||||||
}
|
}
|
||||||
@ -62,17 +51,13 @@ impl Display for RunError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
ArgumentNotRequired(String, usize, String),
|
ArgumentNotRequired(String, usize, String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ParseError {
|
impl Display for ParseError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ParseError::ArgumentNotRequired(name, line_number, line) => write!(
|
ParseError::ArgumentNotRequired(name, line_number, line) => write!(f, "ParseError:\n{1} | {2}\nerror: string argument for {0} not required", name, line_number, line),
|
||||||
f,
|
|
||||||
"ParseError:\n{1} | {2}\nerror: string argument for {0} not required",
|
|
||||||
name, line_number, line
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
189
src/execute.rs
189
src/execute.rs
@ -1,13 +1,10 @@
|
|||||||
use crate::{
|
use crate::{instructions, stack::{Instruction, Stack, StackVec}};
|
||||||
instructions,
|
|
||||||
stack::{Instruction, Stack},
|
|
||||||
};
|
|
||||||
|
|
||||||
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) {
|
||||||
let label = &stack.program[stack.program_counter as usize];
|
let label = &stack.program[stack.program_counter as usize];
|
||||||
stack.program_counter += 1;
|
stack.program_counter += 1;
|
||||||
|
|
||||||
if !label.name.starts_with('@') {
|
if !label.name.starts_with('@') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -28,17 +25,22 @@ fn find_labels(stack: &mut Stack) {
|
|||||||
stack.program_counter = stack.labels[0].unwrap_or(0) as u16;
|
stack.program_counter = stack.labels[0].unwrap_or(0) as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_prefix_operators(instruction: &mut Instruction) {
|
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.ispiped = true;
|
},
|
||||||
}
|
Some('^') => {
|
||||||
Some('/') => {
|
|
||||||
instruction.name = instruction.name.chars().skip(1).collect();
|
instruction.name = instruction.name.chars().skip(1).collect();
|
||||||
|
|
||||||
instruction.isdrained = true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -50,22 +52,7 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
|
|||||||
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) {
|
||||||
stack.program_counter += 1;
|
stack.program_counter += 1;
|
||||||
|
|
||||||
find_prefix_operators(&mut instruction);
|
find_prefix_operators(&mut instruction, &mut stack.memory);
|
||||||
|
|
||||||
if instruction.ispiped {
|
|
||||||
instruction.data = stack.memory.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if instruction.isdrained {
|
|
||||||
stack.memory.push(instruction.data);
|
|
||||||
instruction.data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if instruction.name.chars().nth(0) == Some('#')
|
|
||||||
|| instruction.name.chars().nth(0) == Some('$')
|
|
||||||
{
|
|
||||||
instruction.name = instruction.name.chars().skip(1).collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if instruction.name.starts_with('@') {
|
if instruction.name.starts_with('@') {
|
||||||
continue;
|
continue;
|
||||||
@ -73,120 +60,84 @@ 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::stack_manage::push(&mut stack.memory, instruction.data),
|
"push" => instructions::push::push(&mut stack.memory, instruction.data),
|
||||||
"pop" => instructions::stack_manage::pop(&mut stack.memory),
|
"pop" => instructions::pop::pop(&mut stack.memory),
|
||||||
"dup" => instructions::stack_manage::dup(&mut stack.memory),
|
"dup" => instructions::dup::dup(&mut stack.memory),
|
||||||
"swap" => instructions::stack_manage::swap(&mut stack.memory),
|
"swap" => instructions::swap::swap(&mut stack.memory),
|
||||||
"pick" => instructions::stack_manage::pick(&mut stack.memory, instruction.data),
|
"pick" => instructions::pick::pick(&mut stack.memory, instruction.data),
|
||||||
"string" => instructions::stack_manage::string(&mut stack.memory, instruction.arg.clone()),
|
|
||||||
|
|
||||||
// Math operations
|
// Math
|
||||||
"add" => instructions::math::add(&mut stack.memory),
|
"add" => instructions::add::add(&mut stack.memory),
|
||||||
"sub" => instructions::math::sub(&mut stack.memory),
|
"sub" => instructions::sub::sub(&mut stack.memory),
|
||||||
"mul" => instructions::math::mul(&mut stack.memory),
|
"mul" => instructions::mul::mul(&mut stack.memory),
|
||||||
"div" => instructions::math::div(&mut stack.memory),
|
"div" => instructions::div::div(&mut stack.memory),
|
||||||
"mod" => instructions::math::modulo(&mut stack.memory),
|
"mod" => instructions::modulo::modulo(&mut stack.memory),
|
||||||
|
|
||||||
// Logic
|
// Logic
|
||||||
"and" => instructions::logic::and(&mut stack.memory),
|
"and" => instructions::and::and(&mut stack.memory),
|
||||||
"or" => instructions::logic::or(&mut stack.memory),
|
"or" => instructions::or::or(&mut stack.memory),
|
||||||
"xor" => instructions::logic::xor(&mut stack.memory),
|
"xor" => instructions::xor::xor(&mut stack.memory),
|
||||||
"nand" => instructions::logic::nand(&mut stack.memory),
|
"nand" => instructions::nand::nand(&mut stack.memory),
|
||||||
"not" => instructions::logic::not(&mut stack.memory),
|
"not" => instructions::not::not(&mut stack.memory),
|
||||||
|
|
||||||
// Bitwise
|
// Bitwise
|
||||||
"band" => instructions::bitwise::band(&mut stack.memory),
|
"band" => instructions::band::band(&mut stack.memory),
|
||||||
"bor" => instructions::bitwise::bor(&mut stack.memory),
|
"bor" => instructions::bor::bor(&mut stack.memory),
|
||||||
"bxor" => instructions::bitwise::bxor(&mut stack.memory),
|
"bxor" => instructions::bxor::bxor(&mut stack.memory),
|
||||||
"bnand" => instructions::bitwise::bnand(&mut stack.memory),
|
"bnand" => instructions::bnand::bnand(&mut stack.memory),
|
||||||
"bnot" => instructions::logic::not(&mut stack.memory),
|
"bnot" => instructions::not::not(&mut stack.memory),
|
||||||
|
|
||||||
// Flow-control
|
// Labels
|
||||||
"jmp" => instructions::flow_control::jmp(
|
"jmp" => instructions::jmp::jmp(&mut stack.labels, &mut stack.program_counter, instruction.data),
|
||||||
&mut stack.labels,
|
"rjmp" => instructions::rjmp::rjmp(&mut stack.memory, &mut stack.labels, &mut stack.program_counter),
|
||||||
&mut stack.program_counter,
|
"jnz" => instructions::jnz::jnz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
||||||
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),
|
||||||
"rjmp" => instructions::specific::rjmp(
|
"kjz" => instructions::kjz::kjz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, instruction.data),
|
||||||
&mut stack.memory,
|
|
||||||
&mut stack.labels,
|
|
||||||
&mut stack.program_counter,
|
|
||||||
),
|
|
||||||
"jnz" => instructions::flow_control::jnz(
|
|
||||||
&mut stack.memory,
|
|
||||||
&mut stack.labels,
|
|
||||||
&mut stack.program_counter,
|
|
||||||
instruction.data,
|
|
||||||
),
|
|
||||||
"jz" => instructions::flow_control::jz(
|
|
||||||
&mut stack.memory,
|
|
||||||
&mut stack.labels,
|
|
||||||
&mut stack.program_counter,
|
|
||||||
instruction.data,
|
|
||||||
),
|
|
||||||
"kjnz" => instructions::flow_control::kjnz(
|
|
||||||
&mut stack.memory,
|
|
||||||
&mut stack.labels,
|
|
||||||
&mut stack.program_counter,
|
|
||||||
instruction.data,
|
|
||||||
),
|
|
||||||
"kjz" => instructions::flow_control::kjz(
|
|
||||||
&mut stack.memory,
|
|
||||||
&mut stack.labels,
|
|
||||||
&mut stack.program_counter,
|
|
||||||
instruction.data,
|
|
||||||
),
|
|
||||||
|
|
||||||
// Input/Output
|
// Input/Output
|
||||||
"putc" => instructions::io::putc(&mut stack.memory),
|
"putc" => instructions::putc::putc(&mut stack.memory),
|
||||||
"getc" => instructions::io::getc(&mut stack.memory),
|
"getc" => instructions::getc::getc(&mut stack.memory),
|
||||||
"scan" => instructions::io::scan(&mut stack.memory),
|
"scan" => instructions::scan::scan(&mut stack.memory),
|
||||||
"meow" => instructions::io::meow(&mut stack.memory),
|
"meow" => instructions::meow::meow(&mut stack.memory),
|
||||||
"print" => instructions::io::print(instruction.arg.clone()),
|
"#print" => instructions::print::print(instruction.arg.clone()),
|
||||||
"println" => instructions::io::println(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
|
// Modules
|
||||||
"args" => {
|
"args" => instructions::args::args(&mut stack.memory, &mut origin_stack, instruction.data),
|
||||||
instructions::modules::args(&mut stack.memory, &mut origin_stack, instruction.data)
|
"#exec" => {
|
||||||
}
|
|
||||||
"exec" => {
|
|
||||||
let arg = instruction.arg.clone();
|
let arg = instruction.arg.clone();
|
||||||
instructions::modules::exec(stack, arg, mod_name.clone())
|
instructions::exec::exec(stack, arg, mod_name.clone())
|
||||||
},
|
},
|
||||||
"call" => {
|
|
||||||
let arg = instruction.arg.clone();
|
|
||||||
instructions::modules::call(stack, arg)
|
|
||||||
},
|
|
||||||
"native" => {
|
|
||||||
let arg = instruction.arg.clone();
|
|
||||||
unsafe {instructions::native::native(stack, arg)}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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::self_modify::insert(&mut stack.program, arg, data)
|
instructions::insert::insert(&mut stack.program, arg, data)
|
||||||
}
|
},
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
"dump" => instructions::special::dump(&mut stack.memory),
|
"dump" => instructions::dump::dump(&mut stack.memory),
|
||||||
"size" => instructions::special::size(&mut stack.memory),
|
"size" => instructions::size::size(&mut stack.memory),
|
||||||
"maxsize" => instructions::special::maxsize(&mut stack.memory),
|
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
||||||
"expr" => instructions::special::expr(&mut stack.memory, instruction.arg.clone()),
|
"#expr" => instructions::expr::expr(&mut stack.memory, instruction.arg.clone()),
|
||||||
"field" => continue,
|
"nop" => continue,
|
||||||
"quit" => break,
|
"quit" => break,
|
||||||
"exit" => instructions::special::exit(instruction.data),
|
"exit" => instructions::exit::exit(instruction.data),
|
||||||
|
|
||||||
// Platform-specific
|
// Platform-specific
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
"_unix_random" => instructions::platform_specific::_unix_random(&mut stack.memory),
|
"_unix_random" => instructions::_unix_random::_unix_random(&mut stack.memory),
|
||||||
|
|
||||||
#[cfg(not(target_family = "unix"))]
|
#[cfg(not(target_family = "unix"))]
|
||||||
"_unix_random" => instructions::specific::random(&mut stack.memory),
|
"_unix_random" => instructions::random::random(&mut stack.memory),
|
||||||
|
|
||||||
// Labast-specific
|
// Labast-specific
|
||||||
"random" => instructions::specific::random(&mut stack.memory),
|
"random" => instructions::random::random(&mut stack.memory),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unknown instruction: {}", instruction.name);
|
eprintln!("Unknown instruction: {}", instruction.name);
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
#[cfg(target_family = "unix")]
|
|
||||||
use crate::stack::StackVec;
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
pub fn _unix_random(memory: &mut StackVec) {
|
pub fn _unix_random(memory: &mut StackVec) {
|
||||||
@ -14,4 +11,4 @@ pub fn _unix_random(memory: &mut StackVec) {
|
|||||||
|
|
||||||
let data = memory.pop();
|
let data = memory.pop();
|
||||||
memory.push((u16::from_ne_bytes(buffer)) % (data - 1));
|
memory.push((u16::from_ne_bytes(buffer)) % (data - 1));
|
||||||
}
|
}
|
8
src/instructions/add.rs
Normal file
8
src/instructions/add.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn add(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(a + b);
|
||||||
|
}
|
14
src/instructions/and.rs
Normal file
14
src/instructions/and.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
18
src/instructions/args.rs
Normal file
18
src/instructions/args.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use crate::{errors::RunError, stack::{Stack, StackVec}};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if data == 0 {
|
||||||
|
data = origin_stack.memory.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..data {
|
||||||
|
memory.push(origin_stack.memory.pop());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("{}", RunError::RequestArgsInMainModule);
|
||||||
|
std::process::exit(2);
|
||||||
|
}
|
||||||
|
}
|
8
src/instructions/band.rs
Normal file
8
src/instructions/band.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn band(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(a & b);
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
use crate::stack::StackVec;
|
|
||||||
|
|
||||||
pub fn band(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(a & b);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bor(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(a | b);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bxor(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(a ^ b);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bnand(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(!(a & b));
|
|
||||||
}
|
|
8
src/instructions/bnand.rs
Normal file
8
src/instructions/bnand.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn bnand(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(!(a & b));
|
||||||
|
}
|
8
src/instructions/bor.rs
Normal file
8
src/instructions/bor.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn bor(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(a | b);
|
||||||
|
}
|
8
src/instructions/bxor.rs
Normal file
8
src/instructions/bxor.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn bxor(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(a ^ b);
|
||||||
|
}
|
8
src/instructions/div.rs
Normal file
8
src/instructions/div.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn div(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(b / a);
|
||||||
|
}
|
12
src/instructions/dump.rs
Normal file
12
src/instructions/dump.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn dump(memory: &mut StackVec) {
|
||||||
|
if memory.is_empty() {
|
||||||
|
println!("Stack is empty.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, entry) in memory.iter().enumerate() {
|
||||||
|
println!("{0}: {1}", i, entry);
|
||||||
|
}
|
||||||
|
}
|
6
src/instructions/dup.rs
Normal file
6
src/instructions/dup.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn dup(memory: &mut StackVec) {
|
||||||
|
let data = memory.last();
|
||||||
|
memory.push(data);
|
||||||
|
}
|
19
src/instructions/exec.rs
Normal file
19
src/instructions/exec.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::fs;
|
||||||
|
use crate::{parse, execute, Stack, errors::RunError};
|
||||||
|
|
||||||
|
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(stack.memory.size());
|
||||||
|
|
||||||
|
parse(&mut temp_stack, &lines);
|
||||||
|
execute(&mut temp_stack, Some(&mut stack), arg.clone());
|
||||||
|
|
||||||
|
for item in temp_stack.memory.iter() {
|
||||||
|
stack.memory.push(*item);
|
||||||
|
}
|
||||||
|
}
|
3
src/instructions/exit.rs
Normal file
3
src/instructions/exit.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub fn exit(data: u16) {
|
||||||
|
std::process::exit(data as i32);
|
||||||
|
}
|
@ -1,24 +1,5 @@
|
|||||||
use crate::{errors::RunError, stack::StackVec};
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
pub fn dump(memory: &mut StackVec) {
|
|
||||||
if memory.is_empty() {
|
|
||||||
println!("Stack is empty.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, entry) in memory.iter().enumerate() {
|
|
||||||
println!("{0}: {1}", i, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(memory: &mut StackVec) {
|
|
||||||
memory.push(memory.len() as u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maxsize(memory: &mut StackVec) {
|
|
||||||
memory.push(memory.size() as u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expr(memory: &mut StackVec, arg: String) {
|
pub fn expr(memory: &mut StackVec, arg: String) {
|
||||||
for code in arg.chars() {
|
for code in arg.chars() {
|
||||||
match code {
|
match code {
|
||||||
@ -31,7 +12,7 @@ pub fn expr(memory: &mut StackVec, arg: String) {
|
|||||||
'\\' => {
|
'\\' => {
|
||||||
let ax = memory.pop();
|
let ax = memory.pop();
|
||||||
let ax2 = memory.pop();
|
let ax2 = memory.pop();
|
||||||
|
|
||||||
memory.push(ax);
|
memory.push(ax);
|
||||||
memory.push(ax2);
|
memory.push(ax2);
|
||||||
}
|
}
|
||||||
@ -50,8 +31,4 @@ pub fn expr(memory: &mut StackVec, arg: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exit(data: u16) {
|
|
||||||
std::process::exit(data as i32);
|
|
||||||
}
|
}
|
@ -1,74 +0,0 @@
|
|||||||
use crate::{errors::RunError, stack::StackVec};
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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() != 0 {
|
|
||||||
*program_counter = (labels[data as usize].unwrap() - 1) as 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() {
|
|
||||||
eprintln!("{}", RunError::UnknownLabel(data));
|
|
||||||
std::process::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if memory.pop() == 0 {
|
|
||||||
*program_counter = (labels[data as usize].unwrap() - 1) as 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() {
|
|
||||||
eprintln!("{}", RunError::UnknownLabel(data));
|
|
||||||
std::process::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if memory.last() != 0 {
|
|
||||||
*program_counter = (labels[data as usize].unwrap() - 1) as 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() {
|
|
||||||
eprintln!("{}", RunError::UnknownLabel(data));
|
|
||||||
std::process::exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if memory.last() == 0 {
|
|
||||||
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
|
||||||
}
|
|
||||||
}
|
|
13
src/instructions/getc.rs
Normal file
13
src/instructions/getc.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use std::io::Read;
|
||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
pub fn getc(memory: &mut StackVec) {
|
||||||
|
let char = std::io::stdin()
|
||||||
|
.bytes()
|
||||||
|
.next()
|
||||||
|
.and_then(|result| result.ok())
|
||||||
|
.map(|byte| byte as u16)
|
||||||
|
.expect(&format!("{}", RunError::FailToGetCharFromConsole));
|
||||||
|
|
||||||
|
memory.push(char);
|
||||||
|
}
|
@ -2,27 +2,25 @@ 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] == '$' {
|
||||||
eprintln!("{}", RunError::AttemptToInsertHashOrStringInst);
|
eprintln!("{}", RunError::AttemptToInsertHashOrStringInst);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if args[0] == '\n' {
|
if args[0] == '\n' {
|
||||||
eprintln!("{}", RunError::AttemptToInsertEmptyConst);
|
eprintln!("{}", RunError::AttemptToInsertEmptyConst);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if args[0] == '@' || args[1] == ' ' {
|
if args[0] == '@' || args[1] == ' ' {
|
||||||
eprintln!("{}", RunError::AttemptToInsertALabel);
|
eprintln!("{}", RunError::AttemptToInsertALabel);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
program.push(Instruction {
|
program.push(Instruction {
|
||||||
name: arg.to_string(),
|
name: arg.to_string(),
|
||||||
arg: "\n".to_string(),
|
arg: "\n".to_string(),
|
||||||
data,
|
data
|
||||||
ispiped: false,
|
|
||||||
isdrained: false
|
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -1,43 +0,0 @@
|
|||||||
use crate::{errors::RunError, stack::StackVec};
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
pub fn putc(memory: &mut StackVec) {
|
|
||||||
print!("{}", memory.pop() as u8 as char);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getc(memory: &mut StackVec) {
|
|
||||||
let char = std::io::stdin()
|
|
||||||
.bytes()
|
|
||||||
.next()
|
|
||||||
.and_then(|result| result.ok())
|
|
||||||
.map(|byte| byte as u16)
|
|
||||||
.expect(&format!("{}", RunError::FailToGetCharFromConsole));
|
|
||||||
|
|
||||||
memory.push(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scan(memory: &mut StackVec) {
|
|
||||||
let mut input = String::new();
|
|
||||||
|
|
||||||
std::io::stdin()
|
|
||||||
.read_line(&mut input)
|
|
||||||
.expect(&format!("{}", RunError::FailToReadLineFromConsole));
|
|
||||||
|
|
||||||
let num = input
|
|
||||||
.trim()
|
|
||||||
.parse()
|
|
||||||
.expect(&format!("{}", RunError::InvalidInputUShortInt));
|
|
||||||
memory.push(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn meow(memory: &mut StackVec) {
|
|
||||||
println!("{}", memory.pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print(arg: String) {
|
|
||||||
print!("{}", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn println(arg: String) {
|
|
||||||
println!("{}", arg);
|
|
||||||
}
|
|
10
src/instructions/jmp.rs
Normal file
10
src/instructions/jmp.rs
Normal file
@ -0,0 +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));
|
||||||
|
std::process::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
|
}
|
12
src/instructions/jnz.rs
Normal file
12
src/instructions/jnz.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
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() != 0 {
|
||||||
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
|
}
|
||||||
|
}
|
12
src/instructions/jz.rs
Normal file
12
src/instructions/jz.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
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() == 0 {
|
||||||
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
|
}
|
||||||
|
}
|
12
src/instructions/kjnz.rs
Normal file
12
src/instructions/kjnz.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
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() != 0 {
|
||||||
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
|
}
|
||||||
|
}
|
12
src/instructions/kjz.rs
Normal file
12
src/instructions/kjz.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
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() == 0 {
|
||||||
|
*program_counter = (labels[data as usize].unwrap() - 1) as u16;
|
||||||
|
}
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
use crate::stack::StackVec;
|
|
||||||
|
|
||||||
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 } else { 0 };
|
|
||||||
|
|
||||||
memory.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 } else { 0 };
|
|
||||||
|
|
||||||
memory.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 } else { 0 };
|
|
||||||
|
|
||||||
memory.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 } else { 0 };
|
|
||||||
|
|
||||||
memory.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn not(memory: &mut StackVec) {
|
|
||||||
let a: bool = memory.pop() == 1;
|
|
||||||
|
|
||||||
let c: u16 = if !a { 1 } else { 0 };
|
|
||||||
|
|
||||||
memory.push(c);
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
use crate::stack::StackVec;
|
|
||||||
|
|
||||||
pub fn add(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(a + b);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sub(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(b - a);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mul(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(b * a);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn div(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(b / a);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulo(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(b % a);
|
|
||||||
}
|
|
5
src/instructions/maxsize.rs
Normal file
5
src/instructions/maxsize.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn maxsize(memory: &mut StackVec) {
|
||||||
|
memory.push(memory.size() as u16);
|
||||||
|
}
|
5
src/instructions/meow.rs
Normal file
5
src/instructions/meow.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn meow(memory: &mut StackVec) {
|
||||||
|
println!("{}", memory.pop());
|
||||||
|
}
|
@ -1,12 +1,42 @@
|
|||||||
pub mod bitwise;
|
pub mod push;
|
||||||
pub mod flow_control;
|
pub mod pop;
|
||||||
pub mod io;
|
pub mod dup;
|
||||||
pub mod logic;
|
pub mod swap;
|
||||||
pub mod math;
|
pub mod add;
|
||||||
pub mod modules;
|
pub mod sub;
|
||||||
pub mod platform_specific;
|
pub mod mul;
|
||||||
pub mod self_modify;
|
pub mod div;
|
||||||
pub mod special;
|
pub mod jmp;
|
||||||
pub mod specific;
|
pub mod jnz;
|
||||||
pub mod stack_manage;
|
pub mod jz;
|
||||||
pub mod native;
|
pub mod pick;
|
||||||
|
pub mod putc;
|
||||||
|
pub mod getc;
|
||||||
|
pub mod meow;
|
||||||
|
pub mod dump;
|
||||||
|
pub mod scan;
|
||||||
|
pub mod exec;
|
||||||
|
pub mod args;
|
||||||
|
pub mod expr;
|
||||||
|
pub mod size;
|
||||||
|
pub mod exit;
|
||||||
|
pub mod maxsize;
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
pub mod _unix_random;
|
||||||
|
pub mod modulo;
|
||||||
|
pub mod and;
|
||||||
|
pub mod or;
|
||||||
|
pub mod xor;
|
||||||
|
pub mod nand;
|
||||||
|
pub mod band;
|
||||||
|
pub mod bor;
|
||||||
|
pub mod bxor;
|
||||||
|
pub mod bnand;
|
||||||
|
pub mod not;
|
||||||
|
pub mod kjnz;
|
||||||
|
pub mod kjz;
|
||||||
|
pub mod print;
|
||||||
|
pub mod println;
|
||||||
|
pub mod insert;
|
||||||
|
pub mod random;
|
||||||
|
pub mod rjmp;
|
@ -1,46 +0,0 @@
|
|||||||
use crate::{errors::RunError, execute, parse, stack::StackVec, Stack};
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if data == 0 {
|
|
||||||
data = origin_stack.memory.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
for _ in 0..data {
|
|
||||||
memory.push(origin_stack.memory.pop());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
eprintln!("{}", RunError::RequestArgsInMainModule);
|
|
||||||
std::process::exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(stack.memory.size());
|
|
||||||
|
|
||||||
parse(&mut temp_stack, &lines);
|
|
||||||
execute(&mut temp_stack, Some(&mut stack), arg.clone());
|
|
||||||
|
|
||||||
for item in temp_stack.memory.iter() {
|
|
||||||
stack.memory.push(*item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(stack: &mut Stack, mod_name: String) {
|
|
||||||
let len: u16 = stack.memory.pop();
|
|
||||||
let mut rev: String = String::new();
|
|
||||||
for _i in 0..len {
|
|
||||||
rev.push(stack.memory.pop() as u8 as char);
|
|
||||||
}
|
|
||||||
let tocall: String = rev.chars().rev().collect::<String>();
|
|
||||||
exec(stack, tocall, mod_name);
|
|
||||||
}
|
|
8
src/instructions/modulo.rs
Normal file
8
src/instructions/modulo.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn modulo(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(b % a);
|
||||||
|
}
|
8
src/instructions/mul.rs
Normal file
8
src/instructions/mul.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn mul(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(b * a);
|
||||||
|
}
|
14
src/instructions/nand.rs
Normal file
14
src/instructions/nand.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
@ -1,37 +0,0 @@
|
|||||||
use crate::Stack;
|
|
||||||
use libloading::{Library, Symbol};
|
|
||||||
|
|
||||||
static mut STACKPTR: *mut Stack = 0 as *mut Stack;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern fn stack_pop_callback() -> u16 {
|
|
||||||
(*STACKPTR).memory.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern fn stack_push_callback(data: u16) {
|
|
||||||
(*STACKPTR).memory.push(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern fn stack_len_callback() -> usize {
|
|
||||||
(*STACKPTR).memory.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub unsafe fn native(stack: &mut Stack, arg: String) {
|
|
||||||
STACKPTR = stack as *mut Stack;
|
|
||||||
#[cfg(not(target_family = "windows"))]
|
|
||||||
let libsuf: String = ".so".to_owned();
|
|
||||||
|
|
||||||
#[cfg(target_family = "windows")]
|
|
||||||
let libsuf: String = ".dll".to_owned();
|
|
||||||
|
|
||||||
let module = Library::new(format!("./{}{}", arg, libsuf)).unwrap();
|
|
||||||
// C libraries should use
|
|
||||||
// void (*labashka)(unsigned short (*pop)(void), void (*push)(unsigned short), size_t (*len)(void), size_t max_size);
|
|
||||||
let func: Symbol<unsafe extern "C" fn(unsafe extern fn() -> u16, unsafe extern fn(u16), unsafe extern fn() -> usize, usize)> = module.get(b"labashka").unwrap();
|
|
||||||
func(stack_pop_callback,stack_push_callback,stack_len_callback, stack.memory.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
13
src/instructions/not.rs
Normal file
13
src/instructions/not.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn not(memory: &mut StackVec) {
|
||||||
|
let a: bool = memory.pop() == 1;
|
||||||
|
|
||||||
|
let c: u16 = if !a {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/or.rs
Normal file
14
src/instructions/or.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
11
src/instructions/pick.rs
Normal file
11
src/instructions/pick.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
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();
|
||||||
|
memory.push(*memory.get(memory.len() - (arg as usize) - 1).expect(&format!("{}", RunError::PickOutOfBounds)));
|
||||||
|
}
|
5
src/instructions/pop.rs
Normal file
5
src/instructions/pop.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn pop(memory: &mut StackVec) {
|
||||||
|
memory.pop();
|
||||||
|
}
|
3
src/instructions/print.rs
Normal file
3
src/instructions/print.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub fn print(arg: String) {
|
||||||
|
print!("{}", arg);
|
||||||
|
}
|
3
src/instructions/println.rs
Normal file
3
src/instructions/println.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub fn println(arg: String) {
|
||||||
|
println!("{}", arg);
|
||||||
|
}
|
5
src/instructions/push.rs
Normal file
5
src/instructions/push.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn push(memory: &mut StackVec, data: u16) {
|
||||||
|
memory.push(data);
|
||||||
|
}
|
5
src/instructions/putc.rs
Normal file
5
src/instructions/putc.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn putc(memory: &mut StackVec) {
|
||||||
|
print!("{}", memory.pop() as u8 as char);
|
||||||
|
}
|
7
src/instructions/random.rs
Normal file
7
src/instructions/random.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use fastrand;
|
||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn random(memory: &mut StackVec) {
|
||||||
|
let data = memory.pop();
|
||||||
|
memory.push(fastrand::u16(..) % (data - 1));
|
||||||
|
}
|
9
src/instructions/rjmp.rs
Normal file
9
src/instructions/rjmp.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
pub fn rjmp(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16) {
|
||||||
|
let start = memory.pop() as usize;
|
||||||
|
let end = memory.pop() as usize;
|
||||||
|
let rand = fastrand::usize(start..end + 1);
|
||||||
|
|
||||||
|
*program_counter = (labels[rand].expect(&format!("{}", RunError::UnknownLabel(rand as u16))) - 1) as u16;
|
||||||
|
}
|
10
src/instructions/scan.rs
Normal file
10
src/instructions/scan.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::{errors::RunError, stack::StackVec};
|
||||||
|
|
||||||
|
pub fn scan(memory: &mut StackVec) {
|
||||||
|
let mut input = String::new();
|
||||||
|
|
||||||
|
std::io::stdin().read_line(&mut input).expect(&format!("{}", RunError::FailToReadLineFromConsole));
|
||||||
|
|
||||||
|
let num = input.trim().parse().expect(&format!("{}", RunError::InvalidInputUShortInt));
|
||||||
|
memory.push(num);
|
||||||
|
}
|
5
src/instructions/size.rs
Normal file
5
src/instructions/size.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn size(memory: &mut StackVec) {
|
||||||
|
memory.push(memory.len() as u16);
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
use crate::{errors::RunError, stack::StackVec};
|
|
||||||
use fastrand;
|
|
||||||
|
|
||||||
pub fn random(memory: &mut StackVec) {
|
|
||||||
let data = memory.pop();
|
|
||||||
memory.push(fastrand::u16(..) % (data - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rjmp(memory: &mut StackVec, labels: &mut [Option<i16>; 256], program_counter: &mut u16) {
|
|
||||||
let start = memory.pop() as usize;
|
|
||||||
let end = memory.pop() as usize;
|
|
||||||
let rand = fastrand::usize(start..end + 1);
|
|
||||||
|
|
||||||
*program_counter =
|
|
||||||
(labels[rand].expect(&format!("{}", RunError::UnknownLabel(rand as u16))) - 1) as u16;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
use crate::{errors::RunError, stack::StackVec};
|
|
||||||
|
|
||||||
pub fn push(memory: &mut StackVec, data: u16) {
|
|
||||||
memory.push(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(memory: &mut StackVec) {
|
|
||||||
memory.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dup(memory: &mut StackVec) {
|
|
||||||
let data = memory.last();
|
|
||||||
memory.push(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap(memory: &mut StackVec) {
|
|
||||||
let a: u16 = memory.pop();
|
|
||||||
let b: u16 = memory.pop();
|
|
||||||
|
|
||||||
memory.push(a);
|
|
||||||
memory.push(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
memory.push(
|
|
||||||
*memory
|
|
||||||
.get(memory.len() - (arg as usize) - 1)
|
|
||||||
.expect(&format!("{}", RunError::PickOutOfBounds)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn string(memory: &mut StackVec, arg: String) {
|
|
||||||
for i in arg.chars() {
|
|
||||||
memory.push(i as u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
memory.push(arg.len() as u16);
|
|
||||||
}
|
|
8
src/instructions/sub.rs
Normal file
8
src/instructions/sub.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn sub(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(b - a);
|
||||||
|
}
|
9
src/instructions/swap.rs
Normal file
9
src/instructions/swap.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
pub fn swap(memory: &mut StackVec) {
|
||||||
|
let a: u16 = memory.pop();
|
||||||
|
let b: u16 = memory.pop();
|
||||||
|
|
||||||
|
memory.push(a);
|
||||||
|
memory.push(b);
|
||||||
|
}
|
14
src/instructions/xor.rs
Normal file
14
src/instructions/xor.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::stack::StackVec;
|
||||||
|
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
44
src/main.rs
44
src/main.rs
@ -1,18 +1,15 @@
|
|||||||
use std::{
|
use std::{fs, io::{BufRead, Write}};
|
||||||
fs,
|
|
||||||
io::{BufRead, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use errors::RunError;
|
use errors::RunError;
|
||||||
use execute::execute;
|
use execute::execute;
|
||||||
use parse::parse;
|
use parse::parse;
|
||||||
use stack::Stack;
|
use stack::Stack;
|
||||||
|
|
||||||
mod errors;
|
mod stack;
|
||||||
|
mod parse;
|
||||||
mod execute;
|
mod execute;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
mod parse;
|
mod errors;
|
||||||
mod stack;
|
|
||||||
|
|
||||||
const HELP: &str = "\
|
const HELP: &str = "\
|
||||||
labast - Labaski interpreter written in Rust.
|
labast - Labaski interpreter written in Rust.
|
||||||
@ -42,9 +39,9 @@ fn main() {
|
|||||||
loop {
|
loop {
|
||||||
line.clear();
|
line.clear();
|
||||||
stack.program.clear();
|
stack.program.clear();
|
||||||
|
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
|
|
||||||
print!("> ");
|
print!("> ");
|
||||||
std::io::stdout().flush().expect("Cannot flush the buffer.");
|
std::io::stdout().flush().expect("Cannot flush the buffer.");
|
||||||
|
|
||||||
@ -58,17 +55,7 @@ fn main() {
|
|||||||
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(
|
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")));
|
||||||
&mut stack,
|
|
||||||
None,
|
|
||||||
String::from(
|
|
||||||
input
|
|
||||||
.file_name()
|
|
||||||
.expect("Failed to read file name.")
|
|
||||||
.to_str()
|
|
||||||
.expect("Failed to convert file name to string"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,17 +74,12 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pargs.contains(["-v", "--version"]) {
|
if pargs.contains(["-v", "--version"]) {
|
||||||
println!(
|
println!("labast version {}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
|
||||||
"labast version {}",
|
|
||||||
option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")
|
|
||||||
);
|
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = AppArgs {
|
let args = AppArgs {
|
||||||
stack_size: pargs
|
stack_size: pargs.opt_value_from_fn("--stack-size", parse_stack_size)?.unwrap_or(256),
|
||||||
.opt_value_from_fn("--stack-size", parse_stack_size)?
|
|
||||||
.unwrap_or(256),
|
|
||||||
input: pargs.opt_free_from_str()?,
|
input: pargs.opt_free_from_str()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,14 +92,12 @@ fn parse_args() -> Result<AppArgs, pico_args::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stack_size(s: &str) -> Result<usize, &'static str> {
|
fn parse_stack_size(s: &str) -> Result<usize, &'static str> {
|
||||||
let number = s
|
let number = s.parse().map_err(|_| "Argument for stack size is not a number");
|
||||||
.parse()
|
|
||||||
.map_err(|_| "Argument for stack size is not a number");
|
|
||||||
|
|
||||||
if number > Ok(u16::MAX) {
|
if number > Ok(u16::MAX) {
|
||||||
eprintln!("Stack size cannot be more than 65535");
|
eprintln!("Stack size cannot be more than 65535");
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(number?.into())
|
Ok(number?.into())
|
||||||
}
|
}
|
36
src/parse.rs
36
src/parse.rs
@ -1,7 +1,4 @@
|
|||||||
use crate::{
|
use crate::{errors::ParseError, stack::{Instruction, Stack}};
|
||||||
errors::ParseError,
|
|
||||||
stack::{Instruction, Stack},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn parse(stack: &mut Stack, file_content: &str) {
|
pub fn parse(stack: &mut Stack, file_content: &str) {
|
||||||
for (i, line) in file_content.lines().enumerate() {
|
for (i, line) in file_content.lines().enumerate() {
|
||||||
@ -16,40 +13,31 @@ pub fn parse(stack: &mut Stack, file_content: &str) {
|
|||||||
inst_line = line.trim().chars().collect();
|
inst_line = line.trim().chars().collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
let command: [String; 2] = inst_line.split_once(char::is_whitespace).map_or_else(
|
let command: [String; 2] = inst_line.split_once(char::is_whitespace)
|
||||||
|| [inst_line.trim().to_string(), "".to_string()],
|
.map_or_else(|| [inst_line.trim().to_string(), "".to_string()],
|
||||||
|(first, second)| [first.trim().to_string(), second.trim().to_string()],
|
|(first, second)| [first.trim().to_string(), second.trim().to_string()]);
|
||||||
);
|
|
||||||
|
|
||||||
let name: String = command[0].clone();
|
let name: String;
|
||||||
let mut arg: String = String::new();
|
let mut arg: String = String::new();
|
||||||
let mut data: u16 = 0;
|
let mut data: u16 = 0;
|
||||||
|
|
||||||
|
name = command[0].clone();
|
||||||
|
|
||||||
if !command[1].is_empty() {
|
if !command[1].is_empty() {
|
||||||
if name.chars().nth(0) == Some('#') || name.chars().nth(1) == Some('#') {
|
if name.chars().nth(0) == Some('#') || name.chars().nth(1) == Some('#') {
|
||||||
let splited_data: Vec<String> =
|
let splited_data: Vec<String> = command[1].split_whitespace().map(String::from).collect();
|
||||||
command[1].split_whitespace().map(String::from).collect();
|
|
||||||
arg = splited_data.get(0).unwrap().clone();
|
arg = splited_data.get(0).unwrap().clone();
|
||||||
} else if name.chars().nth(0) == Some('$') || name.chars().nth(1) == Some('$') {
|
} else if name.chars().nth(0) == Some('$') || name.chars().nth(1) == Some('$') {
|
||||||
arg = command[1].clone();
|
arg = command[1].clone();
|
||||||
} else if let Ok(number) = command[1].parse::<i32>() {
|
} else if let Ok(number) = command[1].parse::<i32>() {
|
||||||
data = number as u16;
|
data = number as u16;
|
||||||
} else {
|
} else {
|
||||||
eprintln!(
|
eprintln!("{}", ParseError::ArgumentNotRequired(command[0].to_string(), i + 1, line.to_string()));
|
||||||
"{}",
|
|
||||||
ParseError::ArgumentNotRequired(
|
|
||||||
command[0].to_string(),
|
|
||||||
i + 1,
|
|
||||||
line.to_string()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if name.is_empty() {
|
let inst = Instruction { name, arg, data };
|
||||||
let inst = Instruction { name, arg, data, ispiped: false, isdrained: false };
|
stack.program.push(inst);
|
||||||
stack.program.push(inst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
src/stack.rs
21
src/stack.rs
@ -6,16 +6,14 @@ use crate::errors::StackError;
|
|||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub arg: String,
|
pub arg: String,
|
||||||
pub data: u16,
|
pub data: u16
|
||||||
pub ispiped: bool,
|
|
||||||
pub isdrained: bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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: StackVec,
|
pub memory: StackVec
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
@ -24,14 +22,14 @@ impl Stack {
|
|||||||
program: Vec::new(),
|
program: Vec::new(),
|
||||||
program_counter: 0,
|
program_counter: 0,
|
||||||
labels: [None; 256],
|
labels: [None; 256],
|
||||||
memory: StackVec::new(stack_size),
|
memory: StackVec::new(stack_size)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StackVec {
|
pub struct StackVec {
|
||||||
data: Vec<u16>,
|
data: Vec<u16>,
|
||||||
max_size: usize,
|
max_size: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackVec {
|
impl StackVec {
|
||||||
@ -55,16 +53,11 @@ impl StackVec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop(&mut self) -> u16 {
|
pub fn pop(&mut self) -> u16 {
|
||||||
self.data
|
self.data.pop().expect(&format!("{}", StackError::StackUnderflow))
|
||||||
.pop()
|
|
||||||
.expect(&format!("{}", StackError::StackUnderflow))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last(&mut self) -> u16 {
|
pub fn last(&mut self) -> u16 {
|
||||||
*self
|
*self.data.last().expect(&format!("{}", StackError::StackUnderflow))
|
||||||
.data
|
|
||||||
.last()
|
|
||||||
.expect(&format!("{}", StackError::StackUnderflow))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,4 +67,4 @@ impl Deref for StackVec {
|
|||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.data
|
&self.data
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
@ 0
|
|
||||||
push -1
|
|
||||||
#native native_test
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
// Build with
|
|
||||||
// rustc --crate-type cdylib native_test.rs -o native_test.so
|
|
||||||
// or
|
|
||||||
// rustc --crate-type cdylib native_test.rs -o native_test.dll
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
unsafe extern "C" fn labashka(pop: extern fn() -> u16, push: extern fn(u16), len: extern fn () -> usize, max: usize) {
|
|
||||||
println!("At {}, there's {}.", len(), pop());
|
|
||||||
push(12);
|
|
||||||
println!("Maximum size is {}.", max);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user