Compare commits

...

5 Commits

  1. 4
      Cargo.lock
  2. 4
      Cargo.toml
  3. 2
      README.md
  4. BIN
      logo.png
  5. 81
      src/main.rs

4
Cargo.lock generated

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "ansi_term"
@ -144,7 +144,7 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "mblf"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"anyhow",
"pest",

@ -1,6 +1,6 @@
[package]
name = "mblf"
version = "0.1.0"
version = "0.1.1"
edition = "2018"
description = """
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>"]
repository = "https://github.com/MBLF-Project/mblf"
repository = "https://codeberg.org/MeltingSilicon/compiler-mblf"
license = "MIT OR Apache-2.0"
keywords = ["compiler", "mblf", "brainfuck", "pest"]

@ -1,6 +1,6 @@
# 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

@ -24,13 +24,14 @@ struct MemCell {
}
impl MemCell {
pub fn allocate(address: u32) -> Self {
pub fn allocate_to(address: u32) -> Self {
Self { address }
}
}
struct State {
alloc_cnt: u32,
free_list: Vec<u32>,
mem_pointer: u32,
variables: HashMap<String, MemCell>,
}
@ -71,23 +72,35 @@ fn to_bf(rule: Rule, operand: &str, state: &mut State, out: &mut Builder) {
match rule {
Rule::var => {
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(
String::from(variable_name),
MemCell::allocate(state.alloc_cnt),
MemCell::allocate_to(new_address),
) {
panic!("Variable '{}' already exists", variable_name);
}
state.alloc_cnt += 1;
state.alloc_cnt += mem_extension;
}
Rule::delvar => {
let variable_name = operand;
if state
let memcell = state
.variables
.remove(&String::from(variable_name))
.is_none()
{
panic!("Variable '{}' did not exists", variable_name);
}
.get(variable_name)
.ok_or_else(|| format!("Variable '{variable_name}' did not exists"))
.unwrap();
state.free_list.push(memcell.address);
state.variables.remove(&String::from(variable_name));
}
Rule::point => {
let variable_name = operand;
@ -202,7 +215,7 @@ fn instruct(statement: Pair<Rule>, state: &mut State, out: &mut Builder) {
Rule::include => {
let file_path_raw = extract_operand(statement);
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)
.expect("Parse Error")
.next()
@ -234,6 +247,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut state = State {
alloc_cnt: 0,
free_list: Vec::new(),
mem_pointer: 0,
variables: HashMap::new(),
};
@ -249,3 +263,50 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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"
);
}
}

Loading…
Cancel
Save