forked from n3tael/labast
		
	Initial commit
This commit is contained in:
		
						commit
						a005400477
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
/target
 | 
			
		||||
/archive
 | 
			
		||||
/bin
 | 
			
		||||
							
								
								
									
										7
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
# This file is automatically @generated by Cargo.
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 3
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "labast"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
							
								
								
									
										14
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "labast"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
authors = [ "n3tael" ]
 | 
			
		||||
edition = "2021"
 | 
			
		||||
description = "A zero-dependencies Labaski interpreter written in Rust."
 | 
			
		||||
readme = "README.md"
 | 
			
		||||
license = "MIT"
 | 
			
		||||
publish = false
 | 
			
		||||
 | 
			
		||||
[profile.dev]
 | 
			
		||||
overflow-checks = false
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
							
								
								
									
										21
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2024 n3tael
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
							
								
								
									
										5
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
# Labast
 | 
			
		||||
A zero-dependencies Labaski interpreter written in Rust. Fully supports [Labashki specs 1.4.1](./SPECIFICATION.md).
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
See `example-scripts` directory.
 | 
			
		||||
							
								
								
									
										51
									
								
								SPECIFICATION.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								SPECIFICATION.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
# 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
 | 
			
		||||
Если юзер высрал два лейбла с одинаковыми идентификаторами, то интерпретатор/компилятор должен выдать ошибку
 | 
			
		||||
							
								
								
									
										5
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
@echo off
 | 
			
		||||
cargo build --release
 | 
			
		||||
cargo zigbuild --release --target x86_64-unknown-linux-gnu
 | 
			
		||||
copy target\release\labast.exe bin\ /Y
 | 
			
		||||
copy target\x86_64-unknown-linux-gnu\release\labast bin\ /Y
 | 
			
		||||
							
								
								
									
										9
									
								
								example-scripts/expr.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								example-scripts/expr.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
; written by Labashki developer - aeris
 | 
			
		||||
@ 0
 | 
			
		||||
    #EXPR >++:+\
 | 
			
		||||
    DUMP
 | 
			
		||||
 | 
			
		||||
; Expected output
 | 
			
		||||
;
 | 
			
		||||
; 0: 3
 | 
			
		||||
; 1: 2
 | 
			
		||||
							
								
								
									
										30
									
								
								example-scripts/hello-world.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								example-scripts/hello-world.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +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  ; <space>
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										20
									
								
								example-scripts/labels.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								example-scripts/labels.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
@ 1
 | 
			
		||||
  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
 | 
			
		||||
							
								
								
									
										23
									
								
								example-scripts/math.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								example-scripts/math.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
; Addition
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
; Multiplication
 | 
			
		||||
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
 | 
			
		||||
							
								
								
									
										12
									
								
								example-scripts/modules/main.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								example-scripts/modules/main.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +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
 | 
			
		||||
							
								
								
									
										8
									
								
								example-scripts/modules/second_part.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								example-scripts/modules/second_part.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
PUSH 115 ; s
 | 
			
		||||
PUTC
 | 
			
		||||
PUSH 104 ; h
 | 
			
		||||
PUTC
 | 
			
		||||
PUSH 107 ; k
 | 
			
		||||
PUTC
 | 
			
		||||
PUSH 105 ; i
 | 
			
		||||
PUTC
 | 
			
		||||
							
								
								
									
										15
									
								
								example-scripts/pick.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								example-scripts/pick.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
; written by Labashki developer - aeris
 | 
			
		||||
@ 0
 | 
			
		||||
    PUSH 2
 | 
			
		||||
    PUSH 3
 | 
			
		||||
    PUSH 4
 | 
			
		||||
    PUSH 1
 | 
			
		||||
    PICK
 | 
			
		||||
    DUMP
 | 
			
		||||
 | 
			
		||||
; Expected output
 | 
			
		||||
;
 | 
			
		||||
; 0: 2
 | 
			
		||||
; 1: 3
 | 
			
		||||
; 2: 4
 | 
			
		||||
; 3: 3
 | 
			
		||||
							
								
								
									
										10
									
								
								example-scripts/size.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								example-scripts/size.lb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
@ 0
 | 
			
		||||
    PUSH 1
 | 
			
		||||
    PUSH 2
 | 
			
		||||
    PUSH 3
 | 
			
		||||
    SIZE
 | 
			
		||||
    MEOW
 | 
			
		||||
 | 
			
		||||
; Expected output
 | 
			
		||||
;
 | 
			
		||||
; 3
 | 
			
		||||
							
								
								
									
										45
									
								
								src/errors.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/errors.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
use std::fmt::Display;
 | 
			
		||||
 | 
			
		||||
pub enum RunError {
 | 
			
		||||
    RequestArgsInMainModule,
 | 
			
		||||
    ExecuteItself(String),
 | 
			
		||||
    FailToReadFile,
 | 
			
		||||
    FailToGetCharFromConsole,
 | 
			
		||||
    InvalidInputUShortInt,
 | 
			
		||||
    PickTooDeep,
 | 
			
		||||
    PickOutOfBounds,
 | 
			
		||||
    FailToReadLineFromConsole,
 | 
			
		||||
    UnknownLabel(u16),
 | 
			
		||||
    InvalidExpressionUnknownOperator(String),
 | 
			
		||||
    MemoryEmpty,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for RunError {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            RunError::RequestArgsInMainModule => write!(f, "Can't require arguments in the main module"),
 | 
			
		||||
            RunError::ExecuteItself(mod_name) => write!(f, "Module {}: Can't execute itself", mod_name),
 | 
			
		||||
            RunError::FailToReadFile => write!(f, "Unable to read file"),
 | 
			
		||||
            RunError::FailToGetCharFromConsole => write!(f, "Failed to get character from console"),
 | 
			
		||||
            RunError::InvalidInputUShortInt => write!(f, "Invalid input. Please enter a valid unsigned short integer"),
 | 
			
		||||
            RunError::PickTooDeep => write!(f, "Picking too deep"),
 | 
			
		||||
            RunError::PickOutOfBounds => write!(f, "Trying to get a value out of bounds"),
 | 
			
		||||
            RunError::FailToReadLineFromConsole => write!(f, "Failed to read line from console"),
 | 
			
		||||
            RunError::UnknownLabel(label_name) => write!(f, "Unknown label: {}", label_name),
 | 
			
		||||
            RunError::InvalidExpressionUnknownOperator(name) => write!(f, "Invalid expression: unknown operator '{}'", name),
 | 
			
		||||
            RunError::MemoryEmpty => write!(f, "No elements in memory!"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum ParseError {
 | 
			
		||||
    DataNotAUInt(String, usize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for ParseError {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            ParseError::DataNotAUInt(name, line) => write!(f, "Argument for {0} at {1} isn't a number", name, line),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								src/execute.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/execute.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
use crate::{instructions, stack::Stack};
 | 
			
		||||
 | 
			
		||||
fn find_labels(stack: &mut Stack) {
 | 
			
		||||
    while stack.program_counter < (stack.program.len() as u16) {
 | 
			
		||||
        let label = &stack.program[stack.program_counter as usize];
 | 
			
		||||
        stack.program_counter += 1;
 | 
			
		||||
        
 | 
			
		||||
        if !label.name.starts_with('@') {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if stack.labels[label.data as usize].is_some() {
 | 
			
		||||
            eprintln!("Label {} already defined", label.data);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if label.data == 0 {
 | 
			
		||||
            stack.labels[0] = Some(stack.program_counter as i16);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        stack.labels[label.data as usize] = Some(stack.program_counter as i16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if stack.labels[0].is_some() {
 | 
			
		||||
        stack.program_counter = stack.labels[0].unwrap() as u16;
 | 
			
		||||
    } else {
 | 
			
		||||
        stack.program_counter = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        stack.program_counter += 1;
 | 
			
		||||
        
 | 
			
		||||
        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),
 | 
			
		||||
 | 
			
		||||
            "#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),
 | 
			
		||||
 | 
			
		||||
            // 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),
 | 
			
		||||
 | 
			
		||||
            // Console operations
 | 
			
		||||
            "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),
 | 
			
		||||
 | 
			
		||||
            // ?
 | 
			
		||||
            "NOP"  => continue,
 | 
			
		||||
            "EXIT" => instructions::exit::exit(&instruction.data),
 | 
			
		||||
            "QUIT" => std::process::exit(0),
 | 
			
		||||
 | 
			
		||||
            _ => {
 | 
			
		||||
                eprintln!("Unknown instruction: {}", instruction.name);
 | 
			
		||||
                std::process::exit(2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/instructions/add.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/instructions/add.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn add(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
 | 
			
		||||
    memory.push(a + b);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/instructions/args.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/instructions/args.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
use crate::{errors::RunError, stack::Stack};
 | 
			
		||||
 | 
			
		||||
pub fn args(memory: &mut Vec<u16>, origin_stack: &mut Option<&mut Stack>, data: &u16) {
 | 
			
		||||
    let origin_memory = &mut origin_stack.as_mut().expect("msg").memory;
 | 
			
		||||
 | 
			
		||||
    if *origin_memory == *memory {
 | 
			
		||||
        eprintln!("{}", RunError::RequestArgsInMainModule);
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let quanity: u16;
 | 
			
		||||
    if *data == 0 {
 | 
			
		||||
        quanity = origin_memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    } else {
 | 
			
		||||
        quanity = *data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for _ in 0..quanity {
 | 
			
		||||
        memory.push(origin_memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/instructions/div.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/instructions/div.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn div(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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/instructions/dump.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/instructions/dump.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
pub fn dump(memory: &mut Vec<u16>) {
 | 
			
		||||
    for (i, entry) in memory.iter().enumerate() {
 | 
			
		||||
        println!("{0}: {1}", i, entry);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/instructions/dup.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/instructions/dup.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn dup(memory: &mut Vec<u16>) {
 | 
			
		||||
    memory.push(*memory.last().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								src/instructions/exec.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/instructions/exec.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
use std::fs;
 | 
			
		||||
use crate::{parse, execute, Stack, errors::RunError};
 | 
			
		||||
 | 
			
		||||
pub fn exec(mut stack: &mut Stack, arg: &String, mod_name: &String) {
 | 
			
		||||
    if mod_name == arg {
 | 
			
		||||
        eprintln!("{}", RunError::ExecuteItself(arg.to_string()));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let lines = fs::read_to_string(&arg).expect(&format!("{}", RunError::FailToReadFile));
 | 
			
		||||
    let mut temp_stack = Stack::new();
 | 
			
		||||
 | 
			
		||||
    parse(&mut temp_stack, &lines);
 | 
			
		||||
 | 
			
		||||
    execute(&mut temp_stack, Some(&mut stack), &arg.clone());
 | 
			
		||||
 | 
			
		||||
    for item in temp_stack.memory {
 | 
			
		||||
        stack.memory.push(item);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/instructions/exit.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/instructions/exit.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
pub fn exit(data: &u16) {
 | 
			
		||||
    std::process::exit((*data).into());
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/instructions/expr.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/instructions/expr.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn expr(memory: &mut Vec<u16>, arg: &String) {
 | 
			
		||||
    for code in arg.chars() {
 | 
			
		||||
        match code {
 | 
			
		||||
            '>' => memory.push(0),
 | 
			
		||||
            '$' => { memory.pop(); },
 | 
			
		||||
            ':' => memory.push(*memory.last().expect(&format!("{}", RunError::MemoryEmpty))),
 | 
			
		||||
            '\\' => {
 | 
			
		||||
                let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                let ax2 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                
 | 
			
		||||
                memory.push(ax);
 | 
			
		||||
                memory.push(ax2);
 | 
			
		||||
            }
 | 
			
		||||
            '+' => {
 | 
			
		||||
                let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                memory.push(ax + 1);
 | 
			
		||||
            }
 | 
			
		||||
            '-' => {
 | 
			
		||||
                let ax = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
                memory.push(ax - 1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _ => {
 | 
			
		||||
                eprintln!("{}", RunError::InvalidExpressionUnknownOperator(code.to_string()));
 | 
			
		||||
                std::process::exit(2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/instructions/getc.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/instructions/getc.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn getc(memory: &mut Vec<u16>) {
 | 
			
		||||
    let char = std::io::stdin()
 | 
			
		||||
        .bytes()
 | 
			
		||||
        .next()
 | 
			
		||||
        .and_then(|result| result.ok())
 | 
			
		||||
        .map(|byte| byte as u16)
 | 
			
		||||
        .expect(&format!("{}", RunError::FailToGetCharFromConsole));
 | 
			
		||||
    
 | 
			
		||||
    memory.push(char);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/instructions/jmp.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/instructions/jmp.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn jmp(labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/instructions/jnz.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/instructions/jnz.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn jnz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.pop() != Some(0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/instructions/jz.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/instructions/jz.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn jz(memory: &mut Vec<u16>, labels: &mut [Option<i16>; 256], program_counter: &mut u16, data: &u16) {
 | 
			
		||||
    if labels[*data as usize].is_none() {
 | 
			
		||||
        eprintln!("{}", RunError::UnknownLabel(*data));
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if memory.pop() == Some(0) {
 | 
			
		||||
        *program_counter = (labels[*data as usize].unwrap() - 1) as u16;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/instructions/meow.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/instructions/meow.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn meow(memory: &mut Vec<u16>) {
 | 
			
		||||
    println!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/instructions/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/instructions/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
pub mod push;
 | 
			
		||||
pub mod pop;
 | 
			
		||||
pub mod dup;
 | 
			
		||||
pub mod swap;
 | 
			
		||||
pub mod add;
 | 
			
		||||
pub mod sub;
 | 
			
		||||
pub mod mul;
 | 
			
		||||
pub mod div;
 | 
			
		||||
pub mod jmp;
 | 
			
		||||
pub mod jnz;
 | 
			
		||||
pub mod jz;
 | 
			
		||||
pub mod pick;
 | 
			
		||||
pub mod putc;
 | 
			
		||||
pub mod getc;
 | 
			
		||||
pub mod meow;
 | 
			
		||||
pub mod dump;
 | 
			
		||||
pub mod scan;
 | 
			
		||||
pub mod exec;
 | 
			
		||||
pub mod args;
 | 
			
		||||
pub mod expr;
 | 
			
		||||
pub mod size;
 | 
			
		||||
pub mod exit;
 | 
			
		||||
							
								
								
									
										8
									
								
								src/instructions/mul.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/instructions/mul.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn mul(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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								src/instructions/pick.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/instructions/pick.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn pick(memory: &mut Vec<u16>, data: &u16) {
 | 
			
		||||
    if *data > memory.len() as u16 {
 | 
			
		||||
        eprintln!("{}", RunError::PickTooDeep);
 | 
			
		||||
        std::process::exit(2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let arg = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    memory.push(*memory.get(memory.len() - (arg as usize) - 1).expect(&format!("{}", RunError::PickOutOfBounds)));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/instructions/pop.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/instructions/pop.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
pub fn pop(memory: &mut Vec<u16>) {
 | 
			
		||||
    memory.pop();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/instructions/push.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/instructions/push.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
pub fn push(memory: &mut Vec<u16>, data: &u16) {
 | 
			
		||||
    memory.push(*data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								src/instructions/putc.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/instructions/putc.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn putc(memory: &mut Vec<u16>) {
 | 
			
		||||
    print!("{}", memory.pop().expect(&format!("{}", RunError::MemoryEmpty)) as u8 as char);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/instructions/scan.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/instructions/scan.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn scan(memory: &mut Vec<u16>) {
 | 
			
		||||
    let mut input = String::new();
 | 
			
		||||
 | 
			
		||||
    std::io::stdin().read_line(&mut input).expect(&format!("{}", RunError::FailToReadLineFromConsole));
 | 
			
		||||
                
 | 
			
		||||
    let num = input.trim().parse().expect(&format!("{}", RunError::InvalidInputUShortInt));
 | 
			
		||||
    memory.push(num);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/instructions/size.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/instructions/size.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
pub fn size(memory: &mut Vec<u16>) {
 | 
			
		||||
    memory.push(memory.len() as u16);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/instructions/sub.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/instructions/sub.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn sub(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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/instructions/swap.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/instructions/swap.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
use crate::errors::RunError;
 | 
			
		||||
 | 
			
		||||
pub fn swap(memory: &mut Vec<u16>) {
 | 
			
		||||
    let a: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
    let b: u16 = memory.pop().expect(&format!("{}", RunError::MemoryEmpty));
 | 
			
		||||
 | 
			
		||||
    memory.push(a);
 | 
			
		||||
    memory.push(b);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
use std::{env, fs};
 | 
			
		||||
use errors::RunError;
 | 
			
		||||
use execute::execute;
 | 
			
		||||
use parse::parse;
 | 
			
		||||
use stack::Stack;
 | 
			
		||||
 | 
			
		||||
mod stack;
 | 
			
		||||
mod parse;
 | 
			
		||||
mod execute;
 | 
			
		||||
mod instructions;
 | 
			
		||||
mod errors;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let args: Vec<String> = env::args().collect();
 | 
			
		||||
    
 | 
			
		||||
    if args.len() < 2 {
 | 
			
		||||
        eprintln!("Usage: {0} [FILE]", args[0]);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut stack = Stack::new();
 | 
			
		||||
    let lines = fs::read_to_string(&args[1]).expect(&format!("{}", RunError::FailToReadFile));
 | 
			
		||||
 | 
			
		||||
    parse(&mut stack, &lines);
 | 
			
		||||
 | 
			
		||||
    execute(&mut stack, None, &args[1]);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/parse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/parse.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
use crate::{errors::ParseError, stack::{Instruction, Stack}};
 | 
			
		||||
 | 
			
		||||
pub fn parse(stack: &mut Stack, file_content: &str) {
 | 
			
		||||
    for (i, line) in file_content.lines().enumerate() {
 | 
			
		||||
        if line.trim().starts_with(';') || line.is_empty() {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let inst_line: String;
 | 
			
		||||
        if let Some(comment_index) = line.trim().find(';') {
 | 
			
		||||
            inst_line = line.trim().chars().take(comment_index).collect();
 | 
			
		||||
        } else {
 | 
			
		||||
            inst_line = line.trim().chars().collect();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let command: Vec<String> = inst_line.split_whitespace().map(String::from).collect();
 | 
			
		||||
 | 
			
		||||
        let name: String;
 | 
			
		||||
        let mut arg: String = String::new();
 | 
			
		||||
        let mut data: u16 = 0;
 | 
			
		||||
 | 
			
		||||
        name = command[0].clone();
 | 
			
		||||
 | 
			
		||||
        if command.len() >= 2 {
 | 
			
		||||
            match name.chars().nth(0) {
 | 
			
		||||
                Some('#') => arg = command[1].to_string(),
 | 
			
		||||
                _ => data = command[1].parse().expect(&format!("{}", ParseError::DataNotAUInt(command[0].to_string(), i + 1))),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let inst = Instruction { name, arg, data };
 | 
			
		||||
        stack.program.push(inst);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/stack.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/stack.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Instruction {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub arg: String,
 | 
			
		||||
    pub data: u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Stack {
 | 
			
		||||
    pub program: Vec<Instruction>,
 | 
			
		||||
    pub program_counter: u16,
 | 
			
		||||
    pub labels: [Option<i16>; 256],
 | 
			
		||||
    pub memory: Vec<u16>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Stack {
 | 
			
		||||
    pub fn new() -> Stack {
 | 
			
		||||
        return Stack {
 | 
			
		||||
            program: Vec::new(),
 | 
			
		||||
            program_counter: 0,
 | 
			
		||||
            labels: [None; 256],
 | 
			
		||||
            memory: Vec::new()
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user