update v1.0.3

* fixed _unix_random bug
* add custom instruction "random"
* update to spec 1.12
* more cli options
This commit is contained in:
n3taeli 2024-02-06 19:59:43 +02:00
parent f2b551a586
commit 4fb06f8f34
Signed by: n3tael
GPG Key ID: F305925762F035A8
13 changed files with 174 additions and 34 deletions

18
Cargo.lock generated
View File

@ -2,6 +2,22 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "labast"
version = "1.0.2"
version = "1.0.3"
dependencies = [
"fastrand",
"pico-args",
]
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"

View File

@ -1,6 +1,6 @@
[package]
name = "labast"
version = "1.0.2"
version = "1.0.3"
authors = [ "n3tael" ]
edition = "2021"
description = "A zero-dependencies Labaski interpreter written in Rust."
@ -17,3 +17,5 @@ lto = true
panic = "abort"
[dependencies]
fastrand = "2.0.1"
pico-args = "0.5.0"

View File

@ -1,5 +1,5 @@
# Labast
A zero-dependencies Labaski interpreter written in Rust. Fully supports Labashki specs 1.10.
A Labaski interpreter written in Rust. Fully supports Labashki specs 1.12.
## Examples
See `scripts` directory.

64
npp_labaski.xml Normal file
View File

@ -0,0 +1,64 @@
<NotepadPlus>
<UserLang name="Labashki" ext="lb" udlVersion="2.1">
<Settings>
<Global caseIgnored="no" allowFoldOfComments="no" foldCompact="yes" forcePureLC="0" decimalSeparator="0" />
<Prefix Keywords1="no" Keywords2="no" Keywords3="no" Keywords4="no" Keywords5="yes" Keywords6="no" Keywords7="no" Keywords8="no" />
</Settings>
<KeywordLists>
<Keywords name="Comments">00; 01 02 03 04</Keywords>
<Keywords name="Numbers, prefix1"></Keywords>
<Keywords name="Numbers, prefix2"></Keywords>
<Keywords name="Numbers, extras1"></Keywords>
<Keywords name="Numbers, extras2"></Keywords>
<Keywords name="Numbers, suffix1"></Keywords>
<Keywords name="Numbers, suffix2"></Keywords>
<Keywords name="Numbers, range"></Keywords>
<Keywords name="Operators1">^ |</Keywords>
<Keywords name="Operators2"></Keywords>
<Keywords name="Folders in code1, open"></Keywords>
<Keywords name="Folders in code1, middle"></Keywords>
<Keywords name="Folders in code1, close"></Keywords>
<Keywords name="Folders in code2, open">[</Keywords>
<Keywords name="Folders in code2, middle"></Keywords>
<Keywords name="Folders in code2, close">]</Keywords>
<Keywords name="Folders in comment, open"></Keywords>
<Keywords name="Folders in comment, middle"></Keywords>
<Keywords name="Folders in comment, close"></Keywords>
<Keywords name="Keywords1">#insert</Keywords>
<Keywords name="Keywords2">push pop dup swap pick add sub mul div mod putc getc scan meow args dump maxsize size quit exit _unix_random</Keywords>
<Keywords name="Keywords3">#print $print #exec #expr</Keywords>
<Keywords name="Keywords4">and or xor nand not band bor bxor bnand bnot</Keywords>
<Keywords name="Keywords5">&gt; $ : \ + -</Keywords>
<Keywords name="Keywords6">jmp jnz jz kjnz kjz</Keywords>
<Keywords name="Keywords7">@</Keywords>
<Keywords name="Keywords8">nop</Keywords>
<Keywords name="Delimiters">00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23</Keywords>
</KeywordLists>
<Styles>
<WordsStyle name="DEFAULT" fgColor="F1F2F3" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="COMMENTS" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="LINE COMMENTS" fgColor="57A64A" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="NUMBERS" fgColor="A6CEA8" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS1" fgColor="E67DDC" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS2" fgColor="559CD6" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS3" fgColor="D69D85" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS4" fgColor="FFFF80" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS5" fgColor="FF8080" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS6" fgColor="80FF00" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS7" fgColor="FF80FF" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="KEYWORDS8" fgColor="808080" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="OPERATORS" fgColor="00FFFF" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="FOLDER IN CODE1" fgColor="FF80FF" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="FOLDER IN CODE2" fgColor="FF8040" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="FOLDER IN COMMENT" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS1" fgColor="FF8000" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS2" fgColor="00FF40" bgColor="FFFFFF" colorStyle="1" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS3" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS4" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS5" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS6" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS7" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
<WordsStyle name="DELIMITERS8" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
</Styles>
</UserLang>
</NotepadPlus>

View File

@ -27,4 +27,4 @@ putc
push 105 ; i
putc
push 33 ; !
putc
putc

View File

@ -102,12 +102,14 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
"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),
"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),
// Modules
"args" => instructions::args::args(&mut stack.memory, &mut origin_stack, &instruction.data),
@ -126,18 +128,21 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
},
// Special
"dump" => instructions::dump::dump(&mut stack.memory),
"size" => instructions::size::size(&mut stack.memory),
"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),
"nop" => continue,
"quit" => std::process::exit(0),
"exit" => instructions::exit::exit(&instruction.data),
"#expr" => instructions::expr::expr(&mut stack.memory, &instruction.arg),
"nop" => continue,
"quit" => std::process::exit(0),
"exit" => instructions::exit::exit(&instruction.data),
// Platform-specific
#[cfg(target_family = "unix")]
"_unix_random" => instructions::_unix_random::_unix_random(&mut stack.memory),
// Labast-specific
"random" => instructions::random::random(&mut stack.memory),
_ => {
eprintln!("Unknown instruction: {}", instruction.name);
std::process::exit(2);

View File

@ -6,9 +6,9 @@ use crate::RunError;
pub fn _unix_random(memory: &mut Vec<u16>) {
let mut rng = File::open("/dev/urandom").unwrap();
let mut buffer = [0u8; 1];
let mut buffer = [0u8; 2];
rng.read_exact(&mut buffer).unwrap();
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
memory.push((buffer[0] as u16) % (*data - 1));
memory.push((u16::from_ne_bytes(buffer)) % (*data - 1));
}

View File

@ -1,3 +1,3 @@
pub fn maxsize(memory: &mut Vec<u16>) {
memory.push(65535);
memory.push(u16::MAX);
}

View File

@ -36,4 +36,6 @@ pub mod not;
pub mod kjnz;
pub mod kjz;
pub mod print;
pub mod insert;
pub mod println;
pub mod insert;
pub mod random;

View File

@ -1,3 +1,3 @@
pub fn print(arg: &String) {
println!("{}", arg);
print!("{}", arg);
}

View File

@ -0,0 +1,3 @@
pub fn println(arg: &String) {
println!("{}", arg);
}

View File

@ -0,0 +1,7 @@
use fastrand;
use crate::RunError;
pub fn random(memory: &mut Vec<u16>) {
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
memory.push(fastrand::u16(..) % (*data - 1));
}

View File

@ -1,4 +1,5 @@
use std::{env, fs, io::{BufRead, Write}};
use std::{fs, io::{BufRead, Write}};
use errors::RunError;
use execute::execute;
use parse::parse;
@ -10,17 +11,28 @@ mod execute;
mod instructions;
mod errors;
const HELP: &str = "\
labast - Labaski interpreter written in Rust.
usage: labast [options] [ file.lb ]
options:
-h, --help prints help information
-v, --version prints version
";
fn main() {
let args: Vec<String> = env::args().collect();
let args = match parse_args() {
Ok(v) => v,
Err(e) => {
eprintln!("Error: {}.", e);
std::process::exit(1);
}
};
if args.get(2) == Some(&String::from("-h"))
|| args.get(2) == Some(&String::from("--help")) {
eprintln!("Usage: {0} [file]", args[0]);
return;
}
let mut stack = Stack::new();
if args.len() < 2 {
let mut stack = Stack::new();
if args.input.is_none() {
let mut line = String::new();
loop {
@ -37,12 +49,41 @@ fn main() {
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")));
}
}
#[derive(Debug)]
struct AppArgs {
input: Option<std::path::PathBuf>,
}
fn parse_args() -> Result<AppArgs, pico_args::Error> {
let mut pargs = pico_args::Arguments::from_env();
if pargs.contains(["-h", "--help"]) {
print!("{}", HELP);
std::process::exit(0);
}
let mut stack = Stack::new();
let lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));
if pargs.contains(["-v", "--version"]) {
println!("labast version {}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"));
std::process::exit(0);
}
parse(&mut stack, &lines);
let args = AppArgs {
input: pargs.opt_free_from_str()?,
};
execute(&mut stack, None, &args[1]);
let remaining = pargs.finish();
if !remaining.is_empty() {
eprintln!("Warning: unused arguments left: {:?}.", remaining);
}
return Ok(args);
}