forked from n3tael/labast
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:
parent
f2b551a586
commit
4fb06f8f34
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -2,6 +2,22 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "labast"
|
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"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "labast"
|
name = "labast"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
authors = [ "n3tael" ]
|
authors = [ "n3tael" ]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A zero-dependencies Labaski interpreter written in Rust."
|
description = "A zero-dependencies Labaski interpreter written in Rust."
|
||||||
@ -17,3 +17,5 @@ lto = true
|
|||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
fastrand = "2.0.1"
|
||||||
|
pico-args = "0.5.0"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Labast
|
# 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
|
## Examples
|
||||||
See `scripts` directory.
|
See `scripts` directory.
|
64
npp_labaski.xml
Normal file
64
npp_labaski.xml
Normal 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">> $ : \ + -</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>
|
@ -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),
|
"kjz" => instructions::kjz::kjz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data),
|
||||||
|
|
||||||
// Input/Output
|
// Input/Output
|
||||||
"putc" => instructions::putc::putc(&mut stack.memory),
|
"putc" => instructions::putc::putc(&mut stack.memory),
|
||||||
"getc" => instructions::getc::getc(&mut stack.memory),
|
"getc" => instructions::getc::getc(&mut stack.memory),
|
||||||
"scan" => instructions::scan::scan(&mut stack.memory),
|
"scan" => instructions::scan::scan(&mut stack.memory),
|
||||||
"meow" => instructions::meow::meow(&mut stack.memory),
|
"meow" => instructions::meow::meow(&mut stack.memory),
|
||||||
"#print" => instructions::print::print(&instruction.arg),
|
"#print" => instructions::print::print(&instruction.arg),
|
||||||
"$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
|
// 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),
|
||||||
@ -126,18 +128,21 @@ pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
"dump" => instructions::dump::dump(&mut stack.memory),
|
"dump" => instructions::dump::dump(&mut stack.memory),
|
||||||
"size" => instructions::size::size(&mut stack.memory),
|
"size" => instructions::size::size(&mut stack.memory),
|
||||||
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
"maxsize" => instructions::maxsize::maxsize(&mut stack.memory),
|
||||||
"#expr" => instructions::expr::expr(&mut stack.memory, &instruction.arg),
|
"#expr" => instructions::expr::expr(&mut stack.memory, &instruction.arg),
|
||||||
"nop" => continue,
|
"nop" => continue,
|
||||||
"quit" => std::process::exit(0),
|
"quit" => std::process::exit(0),
|
||||||
"exit" => instructions::exit::exit(&instruction.data),
|
"exit" => instructions::exit::exit(&instruction.data),
|
||||||
|
|
||||||
// Platform-specific
|
// Platform-specific
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
"_unix_random" => instructions::_unix_random::_unix_random(&mut stack.memory),
|
"_unix_random" => instructions::_unix_random::_unix_random(&mut stack.memory),
|
||||||
|
|
||||||
|
// Labast-specific
|
||||||
|
"random" => instructions::random::random(&mut stack.memory),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unknown instruction: {}", instruction.name);
|
eprintln!("Unknown instruction: {}", instruction.name);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
|
@ -6,9 +6,9 @@ use crate::RunError;
|
|||||||
pub fn _unix_random(memory: &mut Vec<u16>) {
|
pub fn _unix_random(memory: &mut Vec<u16>) {
|
||||||
let mut rng = File::open("/dev/urandom").unwrap();
|
let mut rng = File::open("/dev/urandom").unwrap();
|
||||||
|
|
||||||
let mut buffer = [0u8; 1];
|
let mut buffer = [0u8; 2];
|
||||||
rng.read_exact(&mut buffer).unwrap();
|
rng.read_exact(&mut buffer).unwrap();
|
||||||
|
|
||||||
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
let data = &memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
||||||
memory.push((buffer[0] as u16) % (*data - 1));
|
memory.push((u16::from_ne_bytes(buffer)) % (*data - 1));
|
||||||
}
|
}
|
@ -1,3 +1,3 @@
|
|||||||
pub fn maxsize(memory: &mut Vec<u16>) {
|
pub fn maxsize(memory: &mut Vec<u16>) {
|
||||||
memory.push(65535);
|
memory.push(u16::MAX);
|
||||||
}
|
}
|
@ -36,4 +36,6 @@ pub mod not;
|
|||||||
pub mod kjnz;
|
pub mod kjnz;
|
||||||
pub mod kjz;
|
pub mod kjz;
|
||||||
pub mod print;
|
pub mod print;
|
||||||
|
pub mod println;
|
||||||
pub mod insert;
|
pub mod insert;
|
||||||
|
pub mod random;
|
@ -1,3 +1,3 @@
|
|||||||
pub fn print(arg: &String) {
|
pub fn print(arg: &String) {
|
||||||
println!("{}", arg);
|
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);
|
||||||
|
}
|
7
src/instructions/random.rs
Normal file
7
src/instructions/random.rs
Normal 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));
|
||||||
|
}
|
67
src/main.rs
67
src/main.rs
@ -1,4 +1,5 @@
|
|||||||
use std::{env, fs, io::{BufRead, Write}};
|
use std::{fs, io::{BufRead, Write}};
|
||||||
|
|
||||||
use errors::RunError;
|
use errors::RunError;
|
||||||
use execute::execute;
|
use execute::execute;
|
||||||
use parse::parse;
|
use parse::parse;
|
||||||
@ -10,17 +11,28 @@ mod execute;
|
|||||||
mod instructions;
|
mod instructions;
|
||||||
mod errors;
|
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() {
|
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"))
|
let mut stack = Stack::new();
|
||||||
|| args.get(2) == Some(&String::from("--help")) {
|
|
||||||
eprintln!("Usage: {0} [file]", args[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.len() < 2 {
|
if args.input.is_none() {
|
||||||
let mut stack = Stack::new();
|
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -37,12 +49,41 @@ fn main() {
|
|||||||
parse(&mut stack, &line.trim());
|
parse(&mut stack, &line.trim());
|
||||||
execute(&mut stack, None, &"inline".to_string());
|
execute(&mut stack, None, &"inline".to_string());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
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();
|
if pargs.contains(["-v", "--version"]) {
|
||||||
let lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));
|
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);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user