Compare commits
60
Commits
c8126f2891
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99d0f4206c | ||
|
|
8e979d5fe1 | ||
|
|
17d3f54755 | ||
|
|
0e475a7460 | ||
|
|
c08a2fafa7 | ||
|
|
dd91bba51e | ||
|
|
248be40f7d | ||
|
|
13324d8dd4 | ||
|
|
e1b02df0af | ||
|
|
b2067582e0 | ||
|
|
e9ed8b9df1 | ||
|
|
0cca5ebb67 | ||
|
|
1dc545f072 | ||
|
|
45faa754bd | ||
|
|
556a557aee | ||
|
|
52acba8033 | ||
|
|
b0d6627cbd | ||
|
|
206b993b7b | ||
|
|
6402f2b67d | ||
|
|
cdef5393de | ||
|
|
da6c7149f4 | ||
|
|
38c55102df | ||
|
|
3dc0b970fe | ||
|
|
b84e897e29 | ||
|
|
623f68673e | ||
|
|
b27baf921b | ||
|
|
6abc8be2c6 | ||
|
|
85cf8696db | ||
|
|
c2daea0085 | ||
|
|
3c4307022d | ||
|
|
f0015441fd | ||
|
|
5f46fbd760 | ||
|
|
359f144e9a | ||
|
|
837b24e91d | ||
|
|
d2bccced4e | ||
|
|
0535251cda | ||
|
|
06e72b9117 | ||
|
|
27a7a009c1 | ||
|
|
6b0cb46bf6 | ||
|
|
1e2eb0cc23 | ||
|
|
226873e71c | ||
|
|
764b2d17b9 | ||
|
|
ea54bb404d | ||
|
|
db906d1f8a | ||
|
|
08df04a208 | ||
|
|
833e82d5ec | ||
|
|
04b82f997d | ||
|
|
4f8b28f22d | ||
|
|
8d071dc6df | ||
|
|
6a82314e54 | ||
|
|
751dfcd5aa | ||
|
|
bc366b7e1d | ||
|
|
a967f0649f | ||
|
|
9c60b4d6ac | ||
|
|
f3a4b8d98f | ||
|
|
b338363aa5 | ||
|
|
13b29b8bdc | ||
|
|
8bd1224889 | ||
|
|
b5599edd50 | ||
|
|
a651f20078 |
Generated
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
@@ -144,7 +144,7 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mblf"
|
name = "mblf"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"pest",
|
"pest",
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mblf"
|
name = "mblf"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = """
|
description = """
|
||||||
The MBLF-To-BF compiler written in Rust with Pest.
|
The MBLF-To-BF compiler written in Rust with Pest.
|
||||||
@@ -9,7 +9,7 @@ MBLF is a programming language on top of the esoteric programming language Brain
|
|||||||
|
|
||||||
authors = ["Raymon Zutekouw <contact@raymon.dev>"]
|
authors = ["Raymon Zutekouw <contact@raymon.dev>"]
|
||||||
|
|
||||||
repository = "https://github.com/MBLF-Project/mblf"
|
repository = "https://codeberg.org/MeltingSilicon/compiler-mblf"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
keywords = ["compiler", "mblf", "brainfuck", "pest"]
|
keywords = ["compiler", "mblf", "brainfuck", "pest"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# MBLF
|
# MBLF
|
||||||
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/77209611?s=200&v=4" alt="MBLF-logo" width="100px" />
|
<img src="logo.png" alt="MBLF-logo" width="100px" />
|
||||||
|
|
||||||
MBLF is a programming language on top of the esoteric programming language Brainfuck.
|
MBLF is a programming language on top of the esoteric programming language Brainfuck.
|
||||||
|
|
||||||
|
|||||||
+71
-10
@@ -24,13 +24,14 @@ struct MemCell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MemCell {
|
impl MemCell {
|
||||||
pub fn allocate(address: u32) -> Self {
|
pub fn allocate_to(address: u32) -> Self {
|
||||||
Self { address }
|
Self { address }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
alloc_cnt: u32,
|
alloc_cnt: u32,
|
||||||
|
free_list: Vec<u32>,
|
||||||
mem_pointer: u32,
|
mem_pointer: u32,
|
||||||
variables: HashMap<String, MemCell>,
|
variables: HashMap<String, MemCell>,
|
||||||
}
|
}
|
||||||
@@ -71,23 +72,35 @@ fn to_bf(rule: Rule, operand: &str, state: &mut State, out: &mut Builder) {
|
|||||||
match rule {
|
match rule {
|
||||||
Rule::var => {
|
Rule::var => {
|
||||||
let variable_name = operand;
|
let variable_name = operand;
|
||||||
|
|
||||||
|
let mem_extension: u32;
|
||||||
|
let new_address: u32;
|
||||||
|
|
||||||
|
if !state.free_list.is_empty() {
|
||||||
|
new_address = state.free_list.pop().unwrap();
|
||||||
|
mem_extension = 0;
|
||||||
|
} else {
|
||||||
|
new_address = state.alloc_cnt;
|
||||||
|
mem_extension = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(_v) = state.variables.insert(
|
if let Some(_v) = state.variables.insert(
|
||||||
String::from(variable_name),
|
String::from(variable_name),
|
||||||
MemCell::allocate(state.alloc_cnt),
|
MemCell::allocate_to(new_address),
|
||||||
) {
|
) {
|
||||||
panic!("Variable '{}' already exists", variable_name);
|
panic!("Variable '{}' already exists", variable_name);
|
||||||
}
|
}
|
||||||
state.alloc_cnt += 1;
|
state.alloc_cnt += mem_extension;
|
||||||
}
|
}
|
||||||
Rule::delvar => {
|
Rule::delvar => {
|
||||||
let variable_name = operand;
|
let variable_name = operand;
|
||||||
if state
|
let memcell = state
|
||||||
.variables
|
.variables
|
||||||
.remove(&String::from(variable_name))
|
.get(variable_name)
|
||||||
.is_none()
|
.ok_or_else(|| format!("Variable '{variable_name}' did not exists"))
|
||||||
{
|
.unwrap();
|
||||||
panic!("Variable '{}' did not exists", variable_name);
|
state.free_list.push(memcell.address);
|
||||||
}
|
state.variables.remove(&String::from(variable_name));
|
||||||
}
|
}
|
||||||
Rule::point => {
|
Rule::point => {
|
||||||
let variable_name = operand;
|
let variable_name = operand;
|
||||||
@@ -202,7 +215,7 @@ fn instruct(statement: Pair<Rule>, state: &mut State, out: &mut Builder) {
|
|||||||
Rule::include => {
|
Rule::include => {
|
||||||
let file_path_raw = extract_operand(statement);
|
let file_path_raw = extract_operand(statement);
|
||||||
let file_path = &file_path_raw[1..file_path_raw.len() - 1];
|
let file_path = &file_path_raw[1..file_path_raw.len() - 1];
|
||||||
let content = std::fs::read_to_string(&file_path).unwrap();
|
let content = std::fs::read_to_string(file_path).unwrap();
|
||||||
let parsed_file = MblfParser::parse(Rule::file, &content)
|
let parsed_file = MblfParser::parse(Rule::file, &content)
|
||||||
.expect("Parse Error")
|
.expect("Parse Error")
|
||||||
.next()
|
.next()
|
||||||
@@ -234,6 +247,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let mut state = State {
|
let mut state = State {
|
||||||
alloc_cnt: 0,
|
alloc_cnt: 0,
|
||||||
|
free_list: Vec::new(),
|
||||||
mem_pointer: 0,
|
mem_pointer: 0,
|
||||||
variables: HashMap::new(),
|
variables: HashMap::new(),
|
||||||
};
|
};
|
||||||
@@ -249,3 +263,50 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_constant() {
|
||||||
|
assert_eq!(parse_constant("42"), Ok(42));
|
||||||
|
assert_eq!(parse_constant("0x2A"), Ok(42));
|
||||||
|
assert_eq!(parse_constant("\"*\""), Ok(42));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(parse_constant("\'*\'"), Err(std::num::ParseIntError { .. })),
|
||||||
|
"Char literals are declared with \"_\", not \'_\'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_reuse_of_free_memcells() {
|
||||||
|
let mut builder = Builder::default();
|
||||||
|
let mut state = State {
|
||||||
|
alloc_cnt: 0,
|
||||||
|
free_list: Vec::new(),
|
||||||
|
mem_pointer: 0,
|
||||||
|
variables: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
to_bf(Rule::var, "abc", &mut state, &mut builder);
|
||||||
|
assert_eq!(state.alloc_cnt, 1);
|
||||||
|
|
||||||
|
to_bf(Rule::delvar, "abc", &mut state, &mut builder);
|
||||||
|
assert_eq!(
|
||||||
|
state.alloc_cnt, 1,
|
||||||
|
"allocation should not be shrunken, that is too costly"
|
||||||
|
);
|
||||||
|
|
||||||
|
to_bf(Rule::var, "def", &mut state, &mut builder);
|
||||||
|
assert_ne!(
|
||||||
|
state.alloc_cnt, 2,
|
||||||
|
"the just de-allocated memorycell should be re-used"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state.alloc_cnt, 1,
|
||||||
|
"alloc, dealloc, alloc has a max usage of one memorycell"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user