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