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.
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										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),
 | 
			
		||||
 | 
			
		||||
            // 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);
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
}
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
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 kjz;
 | 
			
		||||
pub mod print;
 | 
			
		||||
pub mod println;
 | 
			
		||||
pub mod insert;
 | 
			
		||||
pub mod random;
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
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 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);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user