diff --git a/README.md b/README.md index 0b714b7..09e5688 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # 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 See `scripts` directory. \ No newline at end of file diff --git a/SPECIFICATION.md b/SPECIFICATION.md deleted file mode 100644 index f6c4984..0000000 --- a/SPECIFICATION.md +++ /dev/null @@ -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 -Если юзер высрал два лейбла с одинаковыми идентификаторами, то интерпретатор/компилятор должен выдать ошибку \ No newline at end of file diff --git a/scripts/expr.lb b/scripts/expr.lb index ef58001..3807eae 100644 --- a/scripts/expr.lb +++ b/scripts/expr.lb @@ -1,7 +1,7 @@ ; written by Labashki developer - aeris @ 0 - #EXPR >++:+\ - DUMP + #expr >++:+\ + dump ; Expected output ; diff --git a/scripts/hello-world.lb b/scripts/hello-world.lb index 16c056e..922a4ff 100644 --- a/scripts/hello-world.lb +++ b/scripts/hello-world.lb @@ -1,30 +1,30 @@ -PUSH 72 ; H -PUTC ; Print to console -PUSH 101 ; e -PUTC -PUSH 108 ; l -PUTC -PUSH 108 ; l -PUTC -PUSH 111 ; o -PUTC -PUSH 32 ; -PUTC -PUSH 76 ; L -PUTC -PUSH 97 ; a -PUTC -PUSH 98 ; b -PUTC -PUSH 97 ; a -PUTC -PUSH 115 ; s -PUTC -PUSH 104 ; h -PUTC -PUSH 107 ; k -PUTC -PUSH 105 ; i -PUTC -PUSH 33 ; ! -PUTC \ No newline at end of file +push 72 ; H +putc ; Print to console +push 101 ; e +putc +push 108 ; l +putc +push 108 ; l +putc +push 111 ; o +putc +push 32 ; +putc +push 76 ; L +putc +push 97 ; a +putc +push 98 ; b +putc +push 97 ; a +putc +push 115 ; s +putc +push 104 ; h +putc +push 107 ; k +putc +push 105 ; i +putc +push 33 ; ! +putc \ No newline at end of file diff --git a/scripts/labels.lb b/scripts/labels.lb index df1a64a..2352124 100644 --- a/scripts/labels.lb +++ b/scripts/labels.lb @@ -1,20 +1,20 @@ @ 1 - PUSH 115 ; s - PUTC - PUSH 104 ; h - PUTC - PUSH 107 ; k - PUTC - PUSH 105 ; i - PUTC - EXIT + push 115 ; s + putc + push 104 ; h + putc + push 107 ; k + putc + push 105 ; i + putc + exit @ 0 - PUSH 76 ; L - PUTC - PUSH 97 ; a - PUTC - PUSH 98 ; b - PUTC - PUSH 97 ; a - PUTC - JMP 1 \ No newline at end of file + push 76 ; L + putc + push 97 ; a + putc + push 98 ; b + putc + push 97 ; a + putc + jmp 1 \ No newline at end of file diff --git a/scripts/math.lb b/scripts/math.lb index 3325c7d..c6755a7 100644 --- a/scripts/math.lb +++ b/scripts/math.lb @@ -1,23 +1,23 @@ ; Addition -PUSH 2 ; a = 2 -PUSH 3 ; b = 2 -ADD ; a + b -MEOW ; = 5 +push 2 ; a = 2 +push 3 ; b = 2 +add ; a + b +meow ; = 5 ; Subtraction -PUSH 9 ; a = 9 -PUSH 4 ; b = 4 -SUB ; b - a -MEOW ; = 5 +push 9 ; a = 9 +push 4 ; b = 4 +sub ; b - a +meow ; = 5 ; Multiplication -PUSH 9 ; a = 9 -PUSH 5 ; b = 5 -MUL ; b * a -MEOW ; = 45 +push 9 ; a = 9 +push 5 ; b = 5 +mul ; b * a +meow ; = 45 ; Division -PUSH 81; a = 81 -PUSH 9 ; b = 9 -DIV ; b / a -MEOW ; = 9 \ No newline at end of file +push 81; a = 81 +push 9 ; b = 9 +div ; b / a +meow ; = 9 \ No newline at end of file diff --git a/scripts/modules/main.lb b/scripts/modules/main.lb index 6b2d261..dcac4bf 100644 --- a/scripts/modules/main.lb +++ b/scripts/modules/main.lb @@ -1,12 +1,12 @@ -PUSH 76 ; L -PUTC -PUSH 97 ; a -PUTC -PUSH 98 ; b -PUTC -PUSH 97 ; a -PUTC -#EXEC second_part.lb -PUSH 33 ; ! -PUTC -QUIT \ No newline at end of file +push 76 ; L +putc +push 97 ; a +putc +push 98 ; b +putc +push 97 ; a +putc +#exec second_part.lb +push 33 ; ! +putc +quit \ No newline at end of file diff --git a/scripts/modules/second_part.lb b/scripts/modules/second_part.lb index 7f4d727..ed9d438 100644 --- a/scripts/modules/second_part.lb +++ b/scripts/modules/second_part.lb @@ -1,8 +1,8 @@ -PUSH 115 ; s -PUTC -PUSH 104 ; h -PUTC -PUSH 107 ; k -PUTC -PUSH 105 ; i -PUTC \ No newline at end of file +push 115 ; s +putc +push 104 ; h +putc +push 107 ; k +putc +push 105 ; i +putc \ No newline at end of file diff --git a/scripts/pick.lb b/scripts/pick.lb index 961c0ab..516f097 100644 --- a/scripts/pick.lb +++ b/scripts/pick.lb @@ -1,11 +1,11 @@ ; written by Labashki developer - aeris @ 0 - PUSH 2 - PUSH 3 - PUSH 4 - PUSH 1 - PICK - DUMP + push 2 + push 3 + push 4 + push 1 + pick + dump ; Expected output ; diff --git a/scripts/size.lb b/scripts/size.lb index 336c692..102ad39 100644 --- a/scripts/size.lb +++ b/scripts/size.lb @@ -1,9 +1,9 @@ @ 0 - PUSH 1 - PUSH 2 - PUSH 3 - SIZE - MEOW + push 1 + push 2 + push 3 + size + meow ; Expected output ; diff --git a/scripts/std/rev.lb b/scripts/std/rev.lb index 21f9056..6f835e0 100644 --- a/scripts/std/rev.lb +++ b/scripts/std/rev.lb @@ -1,4 +1,4 @@ ; Labashki standard library ; Written by Labashki developer - aeris -ARGS 0 \ No newline at end of file +args 0 \ No newline at end of file diff --git a/scripts/std/rot.lb b/scripts/std/rot.lb index 469cf7f..869e7e0 100644 --- a/scripts/std/rot.lb +++ b/scripts/std/rot.lb @@ -1,4 +1,4 @@ ; Labashki standard library ; Written by Labashki developer - aeris -ARGS 3 \ No newline at end of file +args 3 \ No newline at end of file diff --git a/scripts/std/unix/ВАРЁНЫЙНОСОК.lb b/scripts/std/unix/ВАРЁНЫЙНОСОК.lb index 99a2bcf..eb81914 100644 --- a/scripts/std/unix/ВАРЁНЫЙНОСОК.lb +++ b/scripts/std/unix/ВАРЁНЫЙНОСОК.lb @@ -1,17 +1,17 @@ ; Labashki standard library ; Written by Labashki developer - aeris -MAXSIZE -ARGS 1 ; Насколько сварить носок -SUB +maxsize +args 1 ; Насколько сварить носок +sub @ 1 - JNZ 2 - QUIT + jnz 2 + quit @ 2 - #EXPR - - PUSH -1 - _UNIX_RANDOM - SWAP - JMP 1 \ No newline at end of file + #expr - + push -1 + _unix_random + swap + jmp 1 \ No newline at end of file diff --git a/scripts/vareniynosok.lb b/scripts/vareniynosok.lb index 3c600cc..4e3a3d7 100644 --- a/scripts/vareniynosok.lb +++ b/scripts/vareniynosok.lb @@ -1,2 +1,2 @@ -SIZE -#EXEC std\unix\ВАРЁНЫЙНОСОК.lb \ No newline at end of file +size +#exec std\unix\ВАРЁНЫЙНОСОК.lb \ No newline at end of file diff --git a/src/execute.rs b/src/execute.rs index 19ac571..9b22fae 100644 --- a/src/execute.rs +++ b/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) { 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) { + 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) { 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; - + + find_prefix_operators(&mut instruction, &mut stack.memory); + if instruction.name.starts_with('@') { continue; } match instruction.name.as_str() { // Stack operations - "PUSH" => instructions::push::push(&mut stack.memory, &instruction.data), - "PICK" => instructions::pick::pick(&mut stack.memory, &instruction.data), - "POP" => instructions::pop::pop(&mut stack.memory), - "DUP" => instructions::dup::dup(&mut stack.memory), - "SWAP" => instructions::swap::swap(&mut stack.memory), - "MEOW" => instructions::meow::meow(&mut stack.memory), - "DUMP" => instructions::dump::dump(&mut stack.memory), - "SIZE" => instructions::size::size(&mut stack.memory), - "MAXSIZE" => instructions::maxsize::maxsize(&mut stack.memory), + "push" => instructions::push::push(&mut stack.memory, &instruction.data), + "pick" => instructions::pick::pick(&mut stack.memory, &instruction.data), + "pop" => instructions::pop::pop(&mut stack.memory), + "dup" => instructions::dup::dup(&mut stack.memory), + "swap" => instructions::swap::swap(&mut stack.memory), + "meow" => instructions::meow::meow(&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), + "#expr" => instructions::expr::expr(&mut stack.memory, &instruction.arg), // Labels - "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), - "JZ" => instructions::jz::jz(&mut stack.memory, &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), + "jz" => instructions::jz::jz(&mut stack.memory, &mut stack.labels, &mut stack.program_counter, &instruction.data), // Math operations - "ADD" => instructions::add::add(&mut stack.memory), - "SUB" => instructions::sub::sub(&mut stack.memory), - "MUL" => instructions::mul::mul(&mut stack.memory), - "DIV" => instructions::div::div(&mut stack.memory), + "add" => instructions::add::add(&mut stack.memory), + "sub" => instructions::sub::sub(&mut stack.memory), + "mul" => instructions::mul::mul(&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 - "PUTC" => instructions::putc::putc(&mut stack.memory), - "GETC" => instructions::getc::getc(&mut stack.memory), - "SCAN" => instructions::scan::scan(&mut stack.memory), + "putc" => instructions::putc::putc(&mut stack.memory), + "getc" => instructions::getc::getc(&mut stack.memory), + "scan" => instructions::scan::scan(&mut stack.memory), // Modules - "ARGS" => instructions::args::args(&mut stack.memory, &mut origin_stack, &instruction.data), - "#EXEC" => instructions::exec::exec(stack, &instruction.arg.clone(), &mod_name), + "args" => instructions::args::args(&mut stack.memory, &mut origin_stack, &instruction.data), + "#exec" => { + let arg = instruction.arg.clone(); + instructions::exec::exec(stack, &arg, &mod_name); + } #[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, - "EXIT" => instructions::exit::exit(&instruction.data), - "QUIT" => std::process::exit(0), + "nop" => continue, + "exit" => instructions::exit::exit(&instruction.data), + "quit" => std::process::exit(0), _ => { eprintln!("Unknown instruction: {}", instruction.name); std::process::exit(2); } } + + std::io::stdin().bytes(); } } \ No newline at end of file diff --git a/src/instructions/and.rs b/src/instructions/and.rs new file mode 100644 index 0000000..c3061d2 --- /dev/null +++ b/src/instructions/and.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn and(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/band.rs b/src/instructions/band.rs new file mode 100644 index 0000000..88e34a4 --- /dev/null +++ b/src/instructions/band.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn band(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/bnand.rs b/src/instructions/bnand.rs new file mode 100644 index 0000000..19fb826 --- /dev/null +++ b/src/instructions/bnand.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn bnand(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/bor.rs b/src/instructions/bor.rs new file mode 100644 index 0000000..69fd8ec --- /dev/null +++ b/src/instructions/bor.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn bor(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/bxor.rs b/src/instructions/bxor.rs new file mode 100644 index 0000000..fc43407 --- /dev/null +++ b/src/instructions/bxor.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn bxor(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 6cf89ee..2239540 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -23,3 +23,13 @@ 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; \ No newline at end of file diff --git a/src/instructions/modulo.rs b/src/instructions/modulo.rs new file mode 100644 index 0000000..c753150 --- /dev/null +++ b/src/instructions/modulo.rs @@ -0,0 +1,8 @@ +use crate::errors::RunError; + +pub fn modulo(memory: &mut Vec) { + let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)); + let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)); + + memory.push(b % a); +} \ No newline at end of file diff --git a/src/instructions/nand.rs b/src/instructions/nand.rs new file mode 100644 index 0000000..c0bd344 --- /dev/null +++ b/src/instructions/nand.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn nand(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/not.rs b/src/instructions/not.rs new file mode 100644 index 0000000..85ea584 --- /dev/null +++ b/src/instructions/not.rs @@ -0,0 +1,13 @@ +use crate::errors::RunError; + +pub fn not(memory: &mut Vec) { + let a: bool = memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) == 1; + + let c: u16 = if !a { + 1 + } else { + 0 + }; + + memory.push(c); +} \ No newline at end of file diff --git a/src/instructions/or.rs b/src/instructions/or.rs new file mode 100644 index 0000000..52c1e02 --- /dev/null +++ b/src/instructions/or.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn or(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/instructions/xor.rs b/src/instructions/xor.rs new file mode 100644 index 0000000..39da94a --- /dev/null +++ b/src/instructions/xor.rs @@ -0,0 +1,14 @@ +use crate::errors::RunError; + +pub fn xor(memory: &mut Vec) { + 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); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 60c70d5..6d1850c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{env, fs}; +use std::{env, fs, io::{BufRead, Write}}; use errors::RunError; use execute::execute; use parse::parse; @@ -12,12 +12,33 @@ mod errors; fn main() { let args: Vec = env::args().collect(); - - if args.len() < 2 { - eprintln!("Usage: {0} [FILE]", args[0]); + + if args.get(2) == Some(&String::from("-h")) + || args.get(2) == Some(&String::from("--help")) { + eprintln!("Usage: {0} [file]", args[0]); 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 lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));