forked from n3tael/labast
update 1.0.2
This commit is contained in:
parent
317fa500b8
commit
a6fbe841f1
@ -1,5 +1,5 @@
|
|||||||
# Labast
|
# Labast
|
||||||
A zero-dependencies Labaski interpreter written in Rust. Fully supports [Labashki specs 1.4.1](./SPECIFICATION.md).
|
A zero-dependencies Labaski interpreter written in Rust. Fully supports Labashki specs 1.7.1.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
See `scripts` directory.
|
See `scripts` directory.
|
@ -1,51 +0,0 @@
|
|||||||
# Labaski specification
|
|
||||||
Last update: 2024-02-05
|
|
||||||
|
|
||||||
Программа состоит из команд в формате `ИНСТРУКЦИЯ АРГУМЕНТ` (assembler-like)
|
|
||||||
|
|
||||||
Аргумент всегда должен быть `uint16` (`unsigned short`, `u16`)
|
|
||||||
|
|
||||||
Все данные которые программа использует хранятся в стеке, сам стек это массив из этих `unsigned short`'ов
|
|
||||||
|
|
||||||
Размер стека без разницы, но желательно минимум 256
|
|
||||||
|
|
||||||
Выполнение программы начинается либо с начала файла, либо с лейбла 0, если он есть
|
|
||||||
|
|
||||||
Почти каждая инструкция которые читает что-то стека должна POP'ать прочитаннное значение
|
|
||||||
|
|
||||||
Если название инструкции начинается с #, то парсер программы должен прочитать аргумент к инструкции как строку(до первого пробела)
|
|
||||||
|
|
||||||
## Инструкции
|
|
||||||
|
|
||||||
| Инструкция | Аргумент | Описание |
|
|
||||||
|-------------|----------------|----------------------------------------------------------------------|
|
|
||||||
| PUSH | `uint16` | Добавить в стек |
|
|
||||||
| POP | - | Удалить из стека |
|
|
||||||
| DUP | - | Дублировать последнее значение в стеке |
|
|
||||||
| SWAP | - | Поменять местами последние 2 значения в стеке |
|
|
||||||
| ADD | - | Прибавление последних 2-х значений из стека |
|
|
||||||
| SUB | - | Вычитание последних 2-х значений из стека |
|
|
||||||
| MUL | - | Умножение последних 2-х значений из стека |
|
|
||||||
| DIV | - | Деление последних 2-х значений из стека |
|
|
||||||
| JMP | `uint16` лейбл | Перейти к лейблу <имя> |
|
|
||||||
| JNZ | `uint16` лейбл | Перейти к лейблу <имя> если значение с верхушки стека не 0 |
|
|
||||||
| JZ | `uint16` лейбл | Перейти к лейблу <имя> если значение с верхушки стека 0 |
|
|
||||||
| NOP | - | Ничего не делает |
|
|
||||||
| EXIT | - | Выход из программы с кодом 0 |
|
|
||||||
| PUTC | - | Вывести символ в консоль |
|
|
||||||
| GETC | - | Получить символ с консоли, добавить символ в стек |
|
|
||||||
| MEOW | - | Принт, POP'ает со стека |
|
|
||||||
| DUMP | - | Вывести весь стек в консоль, понятное дело не попает со стека |
|
|
||||||
| SCAN | - | Сканирует ввод из консоли на `short`'ы и пушит в стек |
|
|
||||||
| #EXEC | arg | Выполнить код из файла, указанного в аргументе* |
|
|
||||||
| ARGS | `uint16` | POP'ает аргумент значений с основного стека и пушит их в стек модуля, если указать аргумент 0, то нужное кол-во аргументов она возьмет(попнув) с оригинального стека |
|
|
||||||
| SIZE | | Пушит в стек значение размера стека |
|
|
||||||
| QUIT | `uint16` | Полностью завершает выполнение программы. Как аргумент попает exit-код. |
|
|
||||||
|
|
||||||
> \*путь относительно места вызова интерпретатора. Создает отдельный стек для модуля, но передает основной для того чтобы взять оттуда аргументы. После того как модуль выполнился, пушит весь стек модуля в основной.
|
|
||||||
|
|
||||||
## Лейблы
|
|
||||||
|
|
||||||
Лейблы могут быть только `unsigned short`'ами
|
|
||||||
От 0 (main-лейбл) до минимум 256
|
|
||||||
Если юзер высрал два лейбла с одинаковыми идентификаторами, то интерпретатор/компилятор должен выдать ошибку
|
|
@ -1,7 +1,7 @@
|
|||||||
; written by Labashki developer - aeris
|
; written by Labashki developer - aeris
|
||||||
@ 0
|
@ 0
|
||||||
#EXPR >++:+\
|
#expr >++:+\
|
||||||
DUMP
|
dump
|
||||||
|
|
||||||
; Expected output
|
; Expected output
|
||||||
;
|
;
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
PUSH 72 ; H
|
push 72 ; H
|
||||||
PUTC ; Print to console
|
putc ; Print to console
|
||||||
PUSH 101 ; e
|
push 101 ; e
|
||||||
PUTC
|
putc
|
||||||
PUSH 108 ; l
|
push 108 ; l
|
||||||
PUTC
|
putc
|
||||||
PUSH 108 ; l
|
push 108 ; l
|
||||||
PUTC
|
putc
|
||||||
PUSH 111 ; o
|
push 111 ; o
|
||||||
PUTC
|
putc
|
||||||
PUSH 32 ; <space>
|
push 32 ; <space>
|
||||||
PUTC
|
putc
|
||||||
PUSH 76 ; L
|
push 76 ; L
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
PUSH 98 ; b
|
push 98 ; b
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
PUSH 115 ; s
|
push 115 ; s
|
||||||
PUTC
|
putc
|
||||||
PUSH 104 ; h
|
push 104 ; h
|
||||||
PUTC
|
putc
|
||||||
PUSH 107 ; k
|
push 107 ; k
|
||||||
PUTC
|
putc
|
||||||
PUSH 105 ; i
|
push 105 ; i
|
||||||
PUTC
|
putc
|
||||||
PUSH 33 ; !
|
push 33 ; !
|
||||||
PUTC
|
putc
|
@ -1,20 +1,20 @@
|
|||||||
@ 1
|
@ 1
|
||||||
PUSH 115 ; s
|
push 115 ; s
|
||||||
PUTC
|
putc
|
||||||
PUSH 104 ; h
|
push 104 ; h
|
||||||
PUTC
|
putc
|
||||||
PUSH 107 ; k
|
push 107 ; k
|
||||||
PUTC
|
putc
|
||||||
PUSH 105 ; i
|
push 105 ; i
|
||||||
PUTC
|
putc
|
||||||
EXIT
|
exit
|
||||||
@ 0
|
@ 0
|
||||||
PUSH 76 ; L
|
push 76 ; L
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
PUSH 98 ; b
|
push 98 ; b
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
JMP 1
|
jmp 1
|
@ -1,23 +1,23 @@
|
|||||||
; Addition
|
; Addition
|
||||||
PUSH 2 ; a = 2
|
push 2 ; a = 2
|
||||||
PUSH 3 ; b = 2
|
push 3 ; b = 2
|
||||||
ADD ; a + b
|
add ; a + b
|
||||||
MEOW ; = 5
|
meow ; = 5
|
||||||
|
|
||||||
; Subtraction
|
; Subtraction
|
||||||
PUSH 9 ; a = 9
|
push 9 ; a = 9
|
||||||
PUSH 4 ; b = 4
|
push 4 ; b = 4
|
||||||
SUB ; b - a
|
sub ; b - a
|
||||||
MEOW ; = 5
|
meow ; = 5
|
||||||
|
|
||||||
; Multiplication
|
; Multiplication
|
||||||
PUSH 9 ; a = 9
|
push 9 ; a = 9
|
||||||
PUSH 5 ; b = 5
|
push 5 ; b = 5
|
||||||
MUL ; b * a
|
mul ; b * a
|
||||||
MEOW ; = 45
|
meow ; = 45
|
||||||
|
|
||||||
; Division
|
; Division
|
||||||
PUSH 81; a = 81
|
push 81; a = 81
|
||||||
PUSH 9 ; b = 9
|
push 9 ; b = 9
|
||||||
DIV ; b / a
|
div ; b / a
|
||||||
MEOW ; = 9
|
meow ; = 9
|
@ -1,12 +1,12 @@
|
|||||||
PUSH 76 ; L
|
push 76 ; L
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
PUSH 98 ; b
|
push 98 ; b
|
||||||
PUTC
|
putc
|
||||||
PUSH 97 ; a
|
push 97 ; a
|
||||||
PUTC
|
putc
|
||||||
#EXEC second_part.lb
|
#exec second_part.lb
|
||||||
PUSH 33 ; !
|
push 33 ; !
|
||||||
PUTC
|
putc
|
||||||
QUIT
|
quit
|
@ -1,8 +1,8 @@
|
|||||||
PUSH 115 ; s
|
push 115 ; s
|
||||||
PUTC
|
putc
|
||||||
PUSH 104 ; h
|
push 104 ; h
|
||||||
PUTC
|
putc
|
||||||
PUSH 107 ; k
|
push 107 ; k
|
||||||
PUTC
|
putc
|
||||||
PUSH 105 ; i
|
push 105 ; i
|
||||||
PUTC
|
putc
|
@ -1,11 +1,11 @@
|
|||||||
; written by Labashki developer - aeris
|
; written by Labashki developer - aeris
|
||||||
@ 0
|
@ 0
|
||||||
PUSH 2
|
push 2
|
||||||
PUSH 3
|
push 3
|
||||||
PUSH 4
|
push 4
|
||||||
PUSH 1
|
push 1
|
||||||
PICK
|
pick
|
||||||
DUMP
|
dump
|
||||||
|
|
||||||
; Expected output
|
; Expected output
|
||||||
;
|
;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
@ 0
|
@ 0
|
||||||
PUSH 1
|
push 1
|
||||||
PUSH 2
|
push 2
|
||||||
PUSH 3
|
push 3
|
||||||
SIZE
|
size
|
||||||
MEOW
|
meow
|
||||||
|
|
||||||
; Expected output
|
; Expected output
|
||||||
;
|
;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
; Labashki standard library
|
; Labashki standard library
|
||||||
; Written by Labashki developer - aeris
|
; Written by Labashki developer - aeris
|
||||||
|
|
||||||
ARGS 0
|
args 0
|
@ -1,4 +1,4 @@
|
|||||||
; Labashki standard library
|
; Labashki standard library
|
||||||
; Written by Labashki developer - aeris
|
; Written by Labashki developer - aeris
|
||||||
|
|
||||||
ARGS 3
|
args 3
|
@ -1,17 +1,17 @@
|
|||||||
; Labashki standard library
|
; Labashki standard library
|
||||||
; Written by Labashki developer - aeris
|
; Written by Labashki developer - aeris
|
||||||
|
|
||||||
MAXSIZE
|
maxsize
|
||||||
ARGS 1 ; Насколько сварить носок
|
args 1 ; Насколько сварить носок
|
||||||
SUB
|
sub
|
||||||
|
|
||||||
@ 1
|
@ 1
|
||||||
JNZ 2
|
jnz 2
|
||||||
QUIT
|
quit
|
||||||
|
|
||||||
@ 2
|
@ 2
|
||||||
#EXPR -
|
#expr -
|
||||||
PUSH -1
|
push -1
|
||||||
_UNIX_RANDOM
|
_unix_random
|
||||||
SWAP
|
swap
|
||||||
JMP 1
|
jmp 1
|
@ -1,2 +1,2 @@
|
|||||||
SIZE
|
size
|
||||||
#EXEC std\unix\ВАРЁНЫЙНОСОК.lb
|
#exec std\unix\ВАРЁНЫЙНОСОК.lb
|
100
src/execute.rs
100
src/execute.rs
@ -1,4 +1,6 @@
|
|||||||
use crate::{instructions, stack::Stack};
|
use std::io::Read;
|
||||||
|
|
||||||
|
use crate::{errors::RunError, 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) {
|
||||||
@ -29,62 +31,102 @@ fn find_labels(stack: &mut Stack) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_prefix_operators(instruction: &mut Instruction, memory: &mut Vec<u16>) {
|
||||||
|
match instruction.name.chars().nth(0) {
|
||||||
|
Some('|') => {
|
||||||
|
instruction.name = instruction.name.chars().skip(1).collect();
|
||||||
|
|
||||||
|
instruction.data = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
||||||
|
},
|
||||||
|
Some('^') => {
|
||||||
|
instruction.name = instruction.name.chars().skip(1).collect();
|
||||||
|
//dbg!(&instruction);
|
||||||
|
if instruction.name.chars().nth(0) != Some('#') {
|
||||||
|
println!("{0} {1}", instruction.name, instruction.data.to_string());
|
||||||
|
} else if instruction.arg.is_empty() {
|
||||||
|
println!("{}", instruction.name);
|
||||||
|
} else {
|
||||||
|
println!("{0} {1}", instruction.name, instruction.arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name: &String) {
|
pub fn execute(stack: &mut Stack, mut origin_stack: Option<&mut Stack>, mod_name: &String) {
|
||||||
find_labels(stack);
|
find_labels(stack);
|
||||||
|
|
||||||
while let Some(instruction) = stack.program.get(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, &mut stack.memory);
|
||||||
|
|
||||||
if instruction.name.starts_with('@') {
|
if instruction.name.starts_with('@') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
match instruction.name.as_str() {
|
match instruction.name.as_str() {
|
||||||
// Stack operations
|
// Stack operations
|
||||||
"PUSH" => instructions::push::push(&mut stack.memory, &instruction.data),
|
"push" => instructions::push::push(&mut stack.memory, &instruction.data),
|
||||||
"PICK" => instructions::pick::pick(&mut stack.memory, &instruction.data),
|
"pick" => instructions::pick::pick(&mut stack.memory, &instruction.data),
|
||||||
"POP" => instructions::pop::pop(&mut stack.memory),
|
"pop" => instructions::pop::pop(&mut stack.memory),
|
||||||
"DUP" => instructions::dup::dup(&mut stack.memory),
|
"dup" => instructions::dup::dup(&mut stack.memory),
|
||||||
"SWAP" => instructions::swap::swap(&mut stack.memory),
|
"swap" => instructions::swap::swap(&mut stack.memory),
|
||||||
"MEOW" => instructions::meow::meow(&mut stack.memory),
|
"meow" => instructions::meow::meow(&mut stack.memory),
|
||||||
"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),
|
||||||
|
|
||||||
// Labels
|
// Labels
|
||||||
"JMP" => instructions::jmp::jmp(&mut stack.labels, &mut stack.program_counter, &instruction.data),
|
"jmp" => instructions::jmp::jmp(&mut stack.labels, &mut stack.program_counter, &instruction.data),
|
||||||
"JNZ" => instructions::jnz::jnz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data),
|
"jnz" => instructions::jnz::jnz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data),
|
||||||
"JZ" => instructions::jz::jz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data),
|
"jz" => instructions::jz::jz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data),
|
||||||
|
|
||||||
// Math operations
|
// Math operations
|
||||||
"ADD" => instructions::add::add(&mut stack.memory),
|
"add" => instructions::add::add(&mut stack.memory),
|
||||||
"SUB" => instructions::sub::sub(&mut stack.memory),
|
"sub" => instructions::sub::sub(&mut stack.memory),
|
||||||
"MUL" => instructions::mul::mul(&mut stack.memory),
|
"mul" => instructions::mul::mul(&mut stack.memory),
|
||||||
"DIV" => instructions::div::div(&mut stack.memory),
|
"div" => instructions::div::div(&mut stack.memory),
|
||||||
|
"mod" => instructions::modulo::modulo(&mut stack.memory),
|
||||||
|
|
||||||
|
"and" => instructions::and::and(&mut stack.memory),
|
||||||
|
"or" => instructions::or::or(&mut stack.memory),
|
||||||
|
"xor" => instructions::xor::xor(&mut stack.memory),
|
||||||
|
"nand" => instructions::nand::nand(&mut stack.memory),
|
||||||
|
"band" => instructions::band::band(&mut stack.memory),
|
||||||
|
"bor" => instructions::bor::bor(&mut stack.memory),
|
||||||
|
"bxor" => instructions::bxor::bxor(&mut stack.memory),
|
||||||
|
"bnand" => instructions::bnand::bnand(&mut stack.memory),
|
||||||
|
"not" => instructions::not::not(&mut stack.memory),
|
||||||
|
|
||||||
// Console operations
|
// Console operations
|
||||||
"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),
|
||||||
|
|
||||||
// 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),
|
||||||
"#EXEC" => instructions::exec::exec(stack, &instruction.arg.clone(), &mod_name),
|
"#exec" => {
|
||||||
|
let arg = instruction.arg.clone();
|
||||||
|
instructions::exec::exec(stack, &arg, &mod_name);
|
||||||
|
}
|
||||||
|
|
||||||
#[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),
|
||||||
|
|
||||||
// ?
|
// ?
|
||||||
"NOP" => continue,
|
"nop" => continue,
|
||||||
"EXIT" => instructions::exit::exit(&instruction.data),
|
"exit" => instructions::exit::exit(&instruction.data),
|
||||||
"QUIT" => std::process::exit(0),
|
"quit" => std::process::exit(0),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unknown instruction: {}", instruction.name);
|
eprintln!("Unknown instruction: {}", instruction.name);
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::io::stdin().bytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
14
src/instructions/and.rs
Normal file
14
src/instructions/and.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn and(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if a && b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/band.rs
Normal file
14
src/instructions/band.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn band(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if a & b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/bnand.rs
Normal file
14
src/instructions/bnand.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn bnand(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if !(a & b) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/bor.rs
Normal file
14
src/instructions/bor.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn bor(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if a | b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/bxor.rs
Normal file
14
src/instructions/bxor.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn bxor(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if a ^ b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
@ -23,3 +23,13 @@ pub mod exit;
|
|||||||
pub mod maxsize;
|
pub mod maxsize;
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
pub mod _unix_random;
|
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;
|
8
src/instructions/modulo.rs
Normal file
8
src/instructions/modulo.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn modulo(memory: &mut Vec<u16>) {
|
||||||
|
let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
||||||
|
let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
|
||||||
|
|
||||||
|
memory.push(b % a);
|
||||||
|
}
|
14
src/instructions/nand.rs
Normal file
14
src/instructions/nand.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn nand(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if !(a && b) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
13
src/instructions/not.rs
Normal file
13
src/instructions/not.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn not(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 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::errors::RunError;
|
||||||
|
|
||||||
|
pub fn or(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if a || b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
14
src/instructions/xor.rs
Normal file
14
src/instructions/xor.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::errors::RunError;
|
||||||
|
|
||||||
|
pub fn xor(memory: &mut Vec<u16>) {
|
||||||
|
let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
let b: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1;
|
||||||
|
|
||||||
|
let c: u16 = if !a != !b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
memory.push(c);
|
||||||
|
}
|
29
src/main.rs
29
src/main.rs
@ -1,4 +1,4 @@
|
|||||||
use std::{env, fs};
|
use std::{env, fs, io::{BufRead, Write}};
|
||||||
use errors::RunError;
|
use errors::RunError;
|
||||||
use execute::execute;
|
use execute::execute;
|
||||||
use parse::parse;
|
use parse::parse;
|
||||||
@ -12,12 +12,33 @@ mod errors;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
if args.len() < 2 {
|
if args.get(2) == Some(&String::from("-h"))
|
||||||
eprintln!("Usage: {0} [FILE]", args[0]);
|
|| args.get(2) == Some(&String::from("--help")) {
|
||||||
|
eprintln!("Usage: {0} [file]", args[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.len() < 2 {
|
||||||
|
let mut stack = Stack::new();
|
||||||
|
let mut line = String::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
line.clear();
|
||||||
|
stack.program.clear();
|
||||||
|
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
|
||||||
|
print!("> ");
|
||||||
|
std::io::stdout().flush().expect("Cannot flush the buffer.");
|
||||||
|
|
||||||
|
stdin.lock().read_line(&mut line).unwrap();
|
||||||
|
|
||||||
|
parse(&mut stack, &line.trim());
|
||||||
|
execute(&mut stack, None, &"inline".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
let lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));
|
let lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user