Skip to content

Commit

Permalink
Merge pull request #1 from Pandicon/Rust-rewrite
Browse files Browse the repository at this point in the history
Interpreter rewrite into Rust
  • Loading branch information
Pandicon committed Aug 9, 2022
2 parents 07d005c + 8a46fd5 commit ae8228f
Show file tree
Hide file tree
Showing 22 changed files with 1,817 additions and 9 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ This language is a fairly good language inspired by a faily popular language cal

## How to run your code <a name="run-code"></a>

All you need to do it run the interpreter file with Python 3.5 and higher.
All you need to do it run the interpreter file with the `run` argument and a path to the maumivu.au file (for example `the-golden run .`). You will have to download a binary from one of the [releases](https://github.com/Pandicon/The-Golden/releases) (I recommend using the [latest one](https://github.com/Pandicon/The-Golden/releases/latest/)). Then you will have to set it up in a way you want - you can either run the binary from a specific place, or set it up as a custom command.

### Arguments <a name="run-code-args"></a>

You can run the code with some arguments including:

- The maumivu.au file location (you will be asked to provide it if you don't include it in the arguments)
- The maumivu.au file location
- Code to run if you don't provide the maumivu.au file location
- Some flags

### Flags <a name="run-code-flags"></a>
Expand All @@ -39,15 +40,16 @@ See the table below for some flags you can provide when running your code.
| --debug | `--debug` | Enabled debug mode - print parsed commands, which command was ran and the memory state at the end of execution |
| --debug-heavy | `--debug-heavy` | Enabled heavy debug mode - print all the things printed in debug mode + stop for 0.5 seconds after each command and print the memory state |
| --disable-warnings | `--disable-warnings` | Disable all warnings |
| --disable-path-warning | `--disable-path-warning` | Disable the "No path provided" warning (fired when running code from args) |
| --disable-too-left-pointer-warning | `--disable-too-left-pointer-warning` | Disable the warning fired when you go to the -1 index in memory |
| --hide-console | `--hide-console` | Hide the console when running the code |
| --version | `--version 0.1.0` | Run the code using a specific version of the interpreter |

## Main features <a name="main-features"></a>

How good or bad the features of this language are is completely subjective, but here are some of them:

- Brainfuck-like syntax - other will have no idea wth your code does
- Easy operations chaining - forget code looking like `>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<<<<<<<<<<<`, now you can do `|49|\,|26|<` to achieve the exact same result
- Easy operations chaining - forget code looking like `>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<<<<<<<<<<<`, now you can do `|49|>\,|26|<` to achieve the exact same result
- Easy arithmetics - tired of multiplication in O(N^2) time? The solution is here! Just do `*` and you are done in ~O(1)
- Decimal numbers - pretty self-explanatory, but now you can use decimal numbers in your code
- And much more!
Expand Down Expand Up @@ -87,16 +89,16 @@ The magic of Brainfuck-like syntax is that it is easy and extremely difficult at
| - | Subtracts the cell in the inactive row from the cell in the active row | `-` | Yes | Yes |
| * | Multiplies the cell in the active row by the cell in the inactive row | `*`| Yes | Yes |
| / | Divides the cell in the active row by the cell in the inactive row |`/`| Yes | Yes |
| _ | Floors the current cell value (towards -infinity) |`_`| No | Yes |
| _ | Floors the current cell value (towards -infinity) |`\_`| No | Yes |
| & | Ceils the current cell value (towards +infinity) |`&`| No | Yes |
| ` | Sets the cell to a random number from 0 (inclusive) to 1 (exclusive) | <code>`</code> | No | Yes |
| > | Move the cell pointer one to the right | `>`| Yes | Yes |
| < | Move the cell pointer one to the left |`<`| Yes | Yes |
| ^ | Switch active memory (sets the active as inactive and the inactive as active) |`^`| No | Yes |
| $. | Sets the cell to the value of user input as a number (if they input 69, the cell value will be 69) |`$.` | No | Yes |
| $. | Sets the cell to the value of user input as a number (if they input 69, the cell value will be 69) | `$.` | No | Yes |
| $, | Sets the cell to the value of user input as a character (if they input E, the cell value will be 69) | `$,`| No | Yes |
| \. | Output the cell as a number (if the cell value is 69, 69 will be printed) |`\.`| No | Yes |
| \, | Output the cell as a character (if the cell value is 69, E will be printed) |`\,`| No | Yes |
| \\. | Output the cell as a number (if the cell value is 69, 69 will be printed) |`\.`| No | Yes |
| \\, | Output the cell as a character (if the cell value is 69, E will be printed) |`\,`| No | Yes |
| [ | Start a while loop |`[` | No | Yes |
| ] | End a while loop | `]` | No | Yes |
| [@ | Start a do-while loop | `[@` | No | Yes |
Expand All @@ -114,7 +116,7 @@ Each line has to end with a punctuation (`:`) or else the program will crash.

- Functions
- Running other files
- A compiled interpreter
- A compiled interpreter ✔️

## Examples <a name="examples"></a>

Expand Down
137 changes: 137 additions & 0 deletions python-interpreter-old/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# The Golden

## Note
This was the first version of the interpreter left here in case it is needed for whatever reason. It will likely not be developped anymore in favour of the Rust one, which can be compiled and ran without Python installed.

## Table of contents

1. [Basic info](#basic-info)
2. [How to run your code](#run-code)<br>
2.1 [Arguments](#run-code-args)<br>
2.2 [Flags](#run-code-flags)
3. [Main features](#main-features)
4. [Important notes](#important-notes)
5. [Mechanics](#mechanics)
6. [Syntax](#syntax)
7. [Incoming features](#incoming-features)
8. [Examples](#examples)

## Basic info <a name="basic-info"></a>

The language is currently in development and there is no stable release yet. There may be a lot of breaking changes introduced in updates.<br>
This language is a fairly good language inspired by a faily popular language called Brainfuck. It takes the beauty of not using any letters in the code from it but also provides some handy features, like printing output as numbers instead of characters and more.
<br>Its purpose is to let people make Brainfuck-styled programs less painfully.

## How to run your code <a name="run-code"></a>

All you need to do it run the interpreter file with Python 3.5 and higher.

### Arguments <a name="run-code-args"></a>

You can run the code with some arguments including:

- The maumivu.au file location (you will be asked to provide it if you don't include it in the arguments)
- Some flags

### Flags <a name="run-code-flags"></a>

See the table below for some flags you can provide when running your code.
| Flag | Usage | Effect |
|:-----|:------|:------|
| - \<code\> | `- '!!![~]:` | You can provide some code to be ran by the interpreter - no need to have a maumivu.au file |
| --debug | `--debug` | Enabled debug mode - print parsed commands, which command was ran and the memory state at the end of execution |
| --debug-heavy | `--debug-heavy` | Enabled heavy debug mode - print all the things printed in debug mode + stop for 0.5 seconds after each command and print the memory state |
| --disable-warnings | `--disable-warnings` | Disable all warnings |
| --disable-path-warning | `--disable-path-warning` | Disable the "No path provided" warning (fired when running code from args) |
| --disable-too-left-pointer-warning | `--disable-too-left-pointer-warning` | Disable the warning fired when you go to the -1 index in memory |

## Main features <a name="main-features"></a>

How good or bad the features of this language are is completely subjective, but here are some of them:

- Brainfuck-like syntax - other will have no idea wth your code does
- Easy operations chaining - forget code looking like `>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.<<<<<<<<<<<<<<<<<<<<<<<<<<`, now you can do `|49|>\,|26|<` to achieve the exact same result
- Easy arithmetics - tired of multiplication in O(N^2) time? The solution is here! Just do `*` and you are done in ~O(1)
- Decimal numbers - pretty self-explanatory, but now you can use decimal numbers in your code
- And much more!

## Important notes <a name="important-notes"></a>

This language uses multiple memory rows - you have access to 2 global memory rows and 2 local memory rows. Both with global and local memory, you are always using just one row at a time. I will be referring to those rows as `active` (the one you are using) and `inactive` (the one you are not using).<br>
Unless said otherwise, `cell` is referring to the selected cell (and also if not said otherwise in the active global memory row).<br>

## Mechanics <a name="mechanics"></a>

The main file has to be named `maumivu.au`. This isn't required with command-line-provided code (obviously).
When converting numbers to characters and vice versa, the ASCII table is used.<br>
The memory has unlimited size and consists of double-precision numbers. When you go to an unexisting index (to the right) that cell is created with the value of 0.<br>
If you go into memory index -1, a 0 is added at that position and the whole memory is shifted one cell to the right. While this is allowed, I would discourage you from doing it since it can be fairly slow (compared to other operations). That's why it will fire a warning.<br>
Loops function the exact same way as in Brainfuck - they only run if the current cell value isn't 0. This language also offers do-while loops, which ignore the check the first time.<br>
You can chain commands by putting `||` in front of them. You can also put a number between those pipes. If you decide to put a number in there, the command right after it will run `floor(the number)` times. If you leave it empty, the code will run `floor(cell value)` times. If the value is negative, the opposite command will be ran (see the table below). If the value is 0, it won't be ran at all.<br>
| Command | Opposite command |
|:-----|:------|
| ! | ~ |
| ~ | ! |
| + | - |
| - | + |
| _ | / |
| / | _ |
| > | < |
| < | > |

## Syntax <a name="syntax"></a>

The magic of Brainfuck-like syntax is that it is easy and extremely difficult at the same time. Here are all the commands the interpreter will understand:
| Command | Explanation | Showcase | Chainable? | Usable on local memory? |
|:-----|:------|:------|:------|:------|
| ! | Adds one to the current cell | `!` | Yes | Yes |
| ~ | Subtracts one from the current cell | `~` | Yes | Yes |
| + | Adds the cell in the inactive row to the cell in the active row | `+` | Yes | Yes |
| - | Subtracts the cell in the inactive row from the cell in the active row | `-` | Yes | Yes |
| * | Multiplies the cell in the active row by the cell in the inactive row | `*`| Yes | Yes |
| / | Divides the cell in the active row by the cell in the inactive row |`/`| Yes | Yes |
| _ | Floors the current cell value (towards -infinity) |`_`| No | Yes |
| & | Ceils the current cell value (towards +infinity) |`&`| No | Yes |
| ` | Sets the cell to a random number from 0 (inclusive) to 1 (exclusive) | <code>`</code> | No | Yes |
| > | Move the cell pointer one to the right | `>`| Yes | Yes |
| < | Move the cell pointer one to the left |`<`| Yes | Yes |
| ^ | Switch active memory (sets the active as inactive and the inactive as active) |`^`| No | Yes |
| $. | Sets the cell to the value of user input as a number (if they input 69, the cell value will be 69) |`$.` | No | Yes |
| $, | Sets the cell to the value of user input as a character (if they input E, the cell value will be 69) | `$,`| No | Yes |
| \\. | Output the cell as a number (if the cell value is 69, 69 will be printed) |`\.`| No | Yes |
| \\, | Output the cell as a character (if the cell value is 69, E will be printed) |`\,`| No | Yes |
| [ | Start a while loop |`[` | No | Yes |
| ] | End a while loop | `]` | No | Yes |
| [@ | Start a do-while loop | `[@` | No | Yes |
| @] | End a do-while loop | `@]` | No | Yes |
| ?? | Sets the cell value to its index | `??` | No | Yes |
| ?= | If the cells in the active and inactive rows have the same value, break the loop | `[?=]` | Yes | Yes |
| ?< | If the cell in the active row has a lower value than the cell in the inactive row, break the loop | `[?<]` | Yes | Yes |
| ?> | If the cell in the active row has a higher value than the cell in the inactive row, break the loop | `[?>]` | Yes | Yes |
| ; | Switch the values of the active global cell and the active local cell | `;` | No | Yes |
| "" | Comments | `"This is a comment"` | No | No |

Each line has to end with a punctuation (`:`) or else the program will crash.

## Incoming features <a name="incoming-features"></a>

- Functions
- Running other files
- A compiled interpreter

## Examples <a name="examples"></a>

Here are some examples written in this language:<br>
"Hello, world!":

```
|72|!\,|29|!\,|7|!\,\,|3|!\,|67|~\,|12|~\,|87|!\,|8|~\,|3|!\,|6|~\,|8|~\,|67|~\,:
```

Fibonacci sequence:

```
!>|10|!<^>|10|!<[@^+\.>\,<@]:
```

You can find all the examples in the [examples folder](https://github.com/Pandicon/The-Golden/tree/main/examples).
File renamed without changes.
14 changes: 14 additions & 0 deletions the-golden/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
18 changes: 18 additions & 0 deletions the-golden/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "the-golden"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dotenv = "0.15.0"
enable-ansi-support = "0.1.2"
lazy_static = "1.4.0"
rand = "0.8.5"
regex = "1.6.0"
tracing = "0.1.35"
tracing-subscriber = "0.3.15"

[target.'cfg(windows)'.dependencies]
winconsole = { version = "0.11.1", features = ["window"] }
1 change: 1 addition & 0 deletions the-golden/maumivu.au
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!|5|!"a"'[!'|-1|![@![!!!@]!]!!'!!'!']""+/`><<_&^|2|!^||~|3|!/&|-3|+$.>$,>$,\.<\,<\,:
8 changes: 8 additions & 0 deletions the-golden/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
hard_tabs = true
max_width = 200
reorder_imports = true
reorder_modules = true
reorder_impl_items = false
report_fixme = "Always"
report_todo = "Always"
edition = "2021"
85 changes: 85 additions & 0 deletions the-golden/src/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#[derive(Clone, Debug)]
pub struct Warnings {
pub too_left_pointer: bool,
}

#[derive(Clone, Debug)]
pub struct Flags {
pub disabled_warnings: Warnings,

pub action: Option<String>,
pub code_path: Option<std::path::PathBuf>,
pub debug: bool,
pub debug_heavy: bool,
pub no_console: bool,
pub raw_code_to_run: Option<String>,
pub version: Option<String>,
}

impl Flags {
pub fn new() -> Self {
Self {
disabled_warnings: Warnings { too_left_pointer: false },

action: None,
code_path: None,
debug: false,
debug_heavy: false,
no_console: false,
raw_code_to_run: None,
version: None,
}
}

pub fn parse(&mut self, args: &[String]) {
let args_count = args.len();
let mut i = 0;
while i < args_count {
let argument = &args[i];
let argument_lowercase = argument.to_lowercase();
match argument_lowercase.as_str() {
"--debug" => self.debug = true,
"--debug-heavy" => {
self.debug = true;
self.debug_heavy = true;
}
"--hide-console" => self.no_console = true,
"--version" => {
if self.version.is_none() && i + 1 < args_count {
self.version = Some(args[i + 1].clone());
}
}
"--disable-warnings" => self.disabled_warnings = Warnings { too_left_pointer: true },
"--disable-too-left-pointer-warning" => self.disabled_warnings.too_left_pointer = true,
"-" => {
if self.raw_code_to_run.is_none() && i + 1 < args_count {
self.raw_code_to_run = Some(args[i + 1].clone());
}
}
"run" => {
if self.action.is_none() {
self.action = Some(String::from("run"));
if self.code_path.is_none() && i + 1 < args_count && !args[i + 1].starts_with('-') {
let mut path = if args[i + 1] != "." && (args[i + 1].starts_with('.') || args[i + 1].starts_with('/')) {
let mut p = std::path::PathBuf::from(args[0].clone());
p.pop();
p.push(args[i + 1].clone());
p
} else {
std::path::PathBuf::from(args[i + 1].clone())
};
if path.is_file() {
path.set_file_name("maumivu.au");
} else {
path.push("maumivu.au");
}
self.code_path = Some(path);
}
}
}
_ => {}
}
i += 1;
}
}
}
34 changes: 34 additions & 0 deletions the-golden/src/interpreter/interpreter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::Flags;

#[path = "./versions/handler.rs"]
mod versions_handler;

pub struct Interpreter {
flags: Flags,

ansi_enabled: bool,
version: String,
versions_handler: versions_handler::Handler,
code: String,
code_path: std::path::PathBuf,
}

impl Interpreter {
pub fn new(mut version: String, code: String, code_path: std::path::PathBuf, flags: Flags, ansi_enabled: bool) -> Self {
let versions_handler = versions_handler::Handler::new();
version = versions_handler.parse_version(version, ansi_enabled);
Self {
flags,
ansi_enabled,
code,
version,
versions_handler,
code_path,
}
}

pub fn run(&self) {
self.versions_handler
.run(self.version.clone(), self.code.clone(), self.code_path.clone(), self.flags.clone(), self.ansi_enabled);
}
}
Loading

0 comments on commit ae8228f

Please sign in to comment.