Skip to content

Commit

Permalink
Merge pull request #3 from Pandicon/dev
Browse files Browse the repository at this point in the history
Version 0.4.0
  • Loading branch information
Pandicon committed Sep 1, 2022
2 parents 99bb885 + c5e9958 commit 0695008
Show file tree
Hide file tree
Showing 15 changed files with 751 additions and 70 deletions.
131 changes: 80 additions & 51 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/fibonacci.au
Original file line number Diff line number Diff line change
@@ -1 +1 @@
!>|10|!<^>|10|!<[@^+\.>\,<@]:
^~^!>|10|!<^>|10|!<[@^+$.>.<@]
2 changes: 1 addition & 1 deletion examples/fibonacci_zero.au
Original file line number Diff line number Diff line change
@@ -1 +1 @@
!>|10|!<^>|10|!<\.>\,<[@^+\.>\,<@]:
^~^!>|10|!<^>|10|!<$.>.<[@^+$.>.<@]
2 changes: 1 addition & 1 deletion examples/hello_world.au
Original file line number Diff line number Diff line change
@@ -1 +1 @@
|72|!\,|29|!\,|7|!\,\,|3|!\,|67|~\,|12|~\,|87|!\,|8|~\,|3|!\,|6|~\,|8|~\,|67|~\,:
|72|!.|29|!.|7|!..|3|!.|67|~.|12|~.|87|!.|8|~.|3|!.|6|~.|8|~.|67|~.
2 changes: 1 addition & 1 deletion the-golden/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "the-golden"
version = "0.3.0"
version = "0.4.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
9 changes: 9 additions & 0 deletions the-golden/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ pub struct Flags {
pub code_path: Option<std::path::PathBuf>,
pub debug: bool,
pub debug_heavy: bool,
pub no_brainfuck: bool,
pub no_console: bool,
pub raw_code_to_run: Option<String>,
pub sebek: [Option<f64>; 3],
pub version: Option<String>,
}

impl Default for Flags {
fn default() -> Self {
Self::new()
}
}

impl Flags {
pub fn new() -> Self {
Self {
Expand All @@ -28,6 +35,7 @@ impl Flags {
code_path: None,
debug: false,
debug_heavy: false,
no_brainfuck: false,
no_console: false,
raw_code_to_run: None,
sebek: [None, None, None],
Expand Down Expand Up @@ -55,6 +63,7 @@ impl Flags {
}
"--disable-warnings" => self.disabled_warnings = Warnings { too_left_pointer: true },
"--disable-too-left-pointer-warning" => self.disabled_warnings.too_left_pointer = true,
"--no-brainfuck" => self.no_brainfuck = true,
"--sebek" => {
if i + 1 < args_count {
self.sebek = Utils::parse_sebek(&args[i + 1]);
Expand Down
1 change: 1 addition & 0 deletions the-golden/src/interpreter/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl Interpreter {
pub fn new(version: Option<String>, code: String, code_path: std::path::PathBuf, mut flags: Flags, ansi_enabled: bool) -> Self {
let mut preprocessor = preprocessor::Preprocessor::new();
preprocessor.run(&code);
flags.no_brainfuck |= preprocessor.no_brainfuck;
flags.no_console |= preprocessor.no_console;
let final_version = if let Some(ver) = version {
ver
Expand Down
6 changes: 6 additions & 0 deletions the-golden/src/interpreter/preprocessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub struct Warnings {
pub struct Preprocessor {
pub disabled_warnings: Warnings,

pub no_brainfuck: bool,
pub no_console: bool,
pub sebek: [Option<f64>; 3],
pub version: Option<String>,
Expand All @@ -21,6 +22,7 @@ impl Preprocessor {
Self {
disabled_warnings: Warnings { too_left_pointer: false },

no_brainfuck: false,
no_console: false,
sebek: [None, None, None],
version: None,
Expand All @@ -36,6 +38,9 @@ impl Preprocessor {
if statement.ends_with(':') {
statement_chars.next_back();
}
if statement.ends_with('#') {
statement_chars.next_back();
}
let args = statement_chars.as_str().split(' ').collect::<Vec<&str>>();
if args.is_empty() {
continue;
Expand All @@ -48,6 +53,7 @@ impl Preprocessor {
}
self.version = Some(args[1].to_string());
}
"nobrainfuck" | "no-brainfuck" | "no_brainfuck" => self.no_brainfuck = true,
"noconsole" | "no-console" | "no_console" => {
if args_count < 2 {
self.no_console = true;
Expand Down
37 changes: 23 additions & 14 deletions the-golden/src/interpreter/versions/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ mod v0_1_0;
mod v0_2_0;
#[path = "./v0-3-0/main.rs"]
mod v0_3_0;
#[path = "./v0-4-0/main.rs"]
mod v0_4_0;

pub struct Handler {
versions: Versions,
Expand All @@ -19,6 +21,7 @@ impl Handler {
Version::new(String::from("1"), vec![Version::new(String::from("0"), vec![])]),
Version::new(String::from("2"), vec![Version::new(String::from("0"), vec![])]),
Version::new(String::from("3"), vec![Version::new(String::from("0"), vec![])]),
Version::new(String::from("4"), vec![Version::new(String::from("0"), vec![])]),
],
);
let versions = Versions::new(vec![versions_0]);
Expand Down Expand Up @@ -81,19 +84,19 @@ impl Handler {
}
version_parsed.push(current_subversion.value.clone());
}
let prerelease = if prerelease.is_some() && !current_subversion.sub.is_empty() {
let ver = prerelease.unwrap();
let mut to_return: Option<&Version> = None;
for subversion in &current_subversion.sub {
if subversion.value == ver {
to_return = Some(subversion);
break;
let prerelease = match (prerelease, !current_subversion.sub.is_empty()) {
(Some(ver), true) => {
let mut to_return: Option<&Version> = None;
for subversion in &current_subversion.sub {
if subversion.value == ver {
to_return = Some(subversion);
break;
}
}
current_subversion = if let Some(to_return) = to_return { to_return } else { current_subversion.sub.last().unwrap() };
format!("-{}", current_subversion.value.clone())
}
current_subversion = if let Some(to_return) = to_return { to_return } else { current_subversion.sub.last().unwrap() };
format!("-{}", current_subversion.value.clone())
} else {
String::new()
_ => String::new(),
};
let version_final = format!("{}{}", version_parsed.join("."), prerelease);
if version_original != version_final && version_original.to_lowercase() != "latest" {
Expand All @@ -111,22 +114,28 @@ impl Handler {
match version.as_str() {
"0.1.0" => {
if flags.debug {
println!("{}Running version 0.1.0", crate::Utils::ansi_escape_text("94", "DEBUG", v0_1_0::INFO_PREFIX_LENGTH, ansi_enabled));
println!("{}Running version {}", crate::Utils::ansi_escape_text("94", "DEBUG", v0_1_0::INFO_PREFIX_LENGTH, ansi_enabled), version);
};
v0_1_0::Runner::new(code, code_path, flags, ansi_enabled).run()
}
"0.2.0" => {
if flags.debug {
println!("{}Running version 0.2.0", crate::Utils::ansi_escape_text("94", "DEBUG", v0_2_0::INFO_PREFIX_LENGTH, ansi_enabled));
println!("{}Running version {}", crate::Utils::ansi_escape_text("94", "DEBUG", v0_2_0::INFO_PREFIX_LENGTH, ansi_enabled), version);
};
v0_2_0::Runner::new(code, code_path, flags, ansi_enabled).run()
}
"0.3.0" => {
if flags.debug {
println!("{}Running version 0.3.0", crate::Utils::ansi_escape_text("94", "DEBUG", v0_3_0::INFO_PREFIX_LENGTH, ansi_enabled));
println!("{}Running version {}", crate::Utils::ansi_escape_text("94", "DEBUG", v0_3_0::INFO_PREFIX_LENGTH, ansi_enabled), version);
};
v0_3_0::Runner::new(code, code_path, flags, ansi_enabled).run()
}
"0.4.0" => {
if flags.debug {
println!("{}Running version {}", crate::Utils::ansi_escape_text("94", "DEBUG", v0_4_0::INFO_PREFIX_LENGTH, ansi_enabled), version);
};
v0_4_0::Runner::new(code, code_path, flags, ansi_enabled).run()
}
_ => {
println!(
"{}Couldn't run version {}",
Expand Down
77 changes: 77 additions & 0 deletions the-golden/src/interpreter/versions/v0-4-0/brackets_matcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::collections::HashMap;

pub struct BracketsMatcher {
pub brackets: HashMap<String, HashMap<usize, usize>>,
brackets_mem: Vec<(String, usize, isize)>,
bracket_keys: HashMap<String, String>,
ending_brackets_keys: HashMap<String, String>
}

impl BracketsMatcher {
pub fn new() -> Self {
Self {
brackets: HashMap::from([
("while".to_string(), HashMap::new()),
("do_while".to_string(), HashMap::new()),
("while_local".to_string(), HashMap::new()),
("do_while_local".to_string(), HashMap::new())
]),
brackets_mem: vec![],
bracket_keys: HashMap::from([
("[".to_string(), "while".to_string()),
("]".to_string(), "while".to_string()),
("[@".to_string(), "do_while".to_string()),
("@]".to_string(), "do_while".to_string()),
("'[".to_string(), "while_local".to_string()),
("']".to_string(), "while_local".to_string()),
("'[@".to_string(), "do_while_local".to_string()),
("'@]".to_string(), "do_while_local".to_string()),
]),
ending_brackets_keys: HashMap::from([
("while".to_string(), "]".to_string()),
("do_while".to_string(), "@]".to_string()),
("while_local".to_string(), "']".to_string()),
("do_while_local".to_string(), "'@]".to_string()),
])
}
}

pub fn match_brackets(&mut self, code: &[String]) {
let starting_brackets = ["[", "[@", "'[", "'[@", ];
let ending_brackets = ["]", "@]", "']", "'@]"];
for (i, command) in code.iter().enumerate() {
let command_str = command.as_str();
if !starting_brackets.contains(&command_str) && !ending_brackets.contains(&command_str) {
continue;
}
if starting_brackets.contains(&command_str) {
self.brackets_mem.push((command.clone(), i, 0));
}
let mut keys_to_remove = vec![];
for key in 0..self.brackets_mem.len() {
self.brackets_mem[key].2 += self.num_equals(&self.brackets_mem[key].0, command);
let wanted_end = self.ending_brackets_keys.get(self.bracket_keys.get(&self.brackets_mem[key].0).unwrap()).unwrap();
if self.brackets_mem[key].2 == 0 && command == wanted_end {
let category = self.bracket_keys.get(wanted_end).unwrap();
let sub_map = self.brackets.get_mut(category).unwrap();
sub_map.insert(self.brackets_mem[key].1, i);
sub_map.insert(i, self.brackets_mem[key].1);
keys_to_remove.push(key);
}
}
for key in keys_to_remove {
self.brackets_mem.remove(key);
}
}
}

fn num_equals(&self, left: &String, right: &String) -> isize {
if self.bracket_keys.get(left) != self.bracket_keys.get(right) {
return 0;
}
if left == right {
return 1;
}
-1
}
}
69 changes: 69 additions & 0 deletions the-golden/src/interpreter/versions/v0-4-0/lexer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use lazy_static::lazy_static;
use regex::Regex;

lazy_static! {
static ref COMMENT_REGEX: Regex = Regex::new("^\"").unwrap();
static ref NEW_LINE_REGEX: Regex = Regex::new(r"^\r?\n").unwrap();
}

#[derive(Clone)]
pub struct Lexer {
text: String,
rules: Vec<Regex>,
line: usize,
column: usize,
comment: bool,
file_path: std::path::PathBuf,
position: usize,
}

impl Lexer {
pub fn new(text: String, rules: Vec<Regex>, file_path: std::path::PathBuf) -> Self {
Self {
text,
rules,
line: 1,
column: 1,
comment: false,
file_path,
position: 0,
}
}

pub fn next(&mut self) -> Result<Option<(String, usize, usize, std::path::PathBuf)>, String> {
let text = &self.text.as_str()[self.position..];
if text.is_empty() {
return Ok(None);
}
if text == "\"" {
self.comment = !self.comment;
}
if self.comment {
return Ok(None);
}
for rule in &self.rules {
if let Some(captures) = rule.captures(text) {
if let Some(capture) = captures.get(0) {
let (command_line, command_column) = (self.line, self.column);
let command = capture.as_str();
let command_length = capture.end() - capture.start();
self.position += command_length;
if command.contains('\n') {
self.line += command.matches('\n').count();
self.column = command.split('\n').last().unwrap().len() + 1;
} else {
self.column += command_length;
}
return Ok(Some((command.to_string(), command_line, command_column, self.file_path.clone())));
}
}
}
Err(format!(
"Syntax error at {}:{} in {:?} ({:?})",
self.line,
self.column,
self.file_path.file_name().unwrap(),
self.file_path.as_path()
))
}
}
Loading

0 comments on commit 0695008

Please sign in to comment.