Skip to content

Commit

Permalink
Added duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyllingene committed Sep 18, 2023
1 parent 33dfa49 commit 7a8cfed
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "brim"
version = "3.0.2"
version = "3.0.3"
edition = "2021"

description = "An optimizing brain* interpreter."
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ a single "instruction". Currently, it recognizes:
- Also recognizes multiplication (`[->+++<]`)
- Subtracting one cell from another (`[->-<]`)
- Scanning for a zero cell (`[>>>]`)
- Duplicating a cell (`[->+>+<<]`)
- Also recognizes multiplication (as with moving)

The token-based structure makes these trivial to recognize, since repeating
instructions have already been collapsed into one.
Expand All @@ -64,8 +66,8 @@ functions, as well as the `Token` enum.
Brim isn't finished yet! My hopes for the future include:

- More macro-optimizations
- Heavy micro-optimization of brim itself
- More variations (non-wrapping, signed, varying tape size)
- Tape customizations via features
- Cell behavior variants via features

## Contributions

Expand Down
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ pub fn interpret(code: &[Token], stdin: &mut impl Iterator<Item = u8>, stdout: &
*cell = cell.wrapping_sub(v);
tape[sp] = 0;
}
Token::Dup(i1, mul1, i2, mul2) => {
let v = tape[sp];

let cell = &mut tape[wrap_goto(sp, i1)];
*cell = cell.wrapping_add(v * mul1);

let cell = &mut tape[wrap_goto(sp, i1 + i2)];
*cell = cell.wrapping_add(v * mul2);

tape[sp] = 0;
}
Token::Scan(i) => {
while tape[sp] != 0 {
sp = wrap_goto(sp, i);
Expand Down
123 changes: 101 additions & 22 deletions src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub enum Token {
Add(isize, u8),
/// Macro-optimization. Equivalent to `[->-<]`.
Sub(isize),
/// Macro-optimization. Equivalent to `[->+>+<<]`.
Dup(isize, u8, isize, u8),
/// Macro-optimization. Equivalent to `[>>>]`.
Scan(isize),

Expand Down Expand Up @@ -127,12 +129,17 @@ pub fn optimize(toks: &[Token]) -> Vec<Token> {
if matches!(tok, Token::LBrack(_)) {
let next = toks.get(si + 1);

// Zero / Set / Add / Sub
// [
// Zero / Set / Add / Sub / Dup
if matches!(next, Some(Token::Dec(1))) {
let next = toks.get(si + 2);

// [-
// Zero / Set
if matches!(next, Some(Token::RBrack(_))) {
// [-]
if let Some(Token::Inc(i)) = toks.get(si + 3) {
// [-]+++
out.push(Token::Set(*i));

si += 4;
Expand All @@ -144,19 +151,45 @@ pub fn optimize(toks: &[Token]) -> Vec<Token> {

continue;

// Add / Sub
// [-
// Add / Sub / Dup
} else if let Some(Token::Goto(there)) = next {
let next = toks.get(si + 3);

// Add
// [->
// Add / Dup
if let Some(Token::Inc(mul)) = next {
if let Some(Token::Goto(back)) = toks.get(si + 4) {
if *there == -back && matches!(toks.get(si + 5), Some(Token::RBrack(_)))
{
out.push(Token::Add(*there, *mul));

si += 6;
continue;
let next = toks.get(si + 5);

// [->+ ><
// Add
if *there == -back {
// [->+<
if matches!(next, Some(Token::RBrack(_))) {
// [->+<]
out.push(Token::Add(*there, *mul));

si += 6;
continue;
}

// [->+ ><
// Dup
} else if let Some(Token::Inc(mul2)) = next {
// [->+ >< +
if let Some(Token::Goto(bi)) = toks.get(si + 6) {
// [->+ >< + ><
if bi + there + back == 0
// [->+>+<<]
&& matches!(toks.get(si + 7), Some(Token::RBrack(_)))
{
out.push(Token::Dup(*there, *mul, *back, *mul2));

si += 8;
continue;
}
}
}
}

Expand All @@ -174,21 +207,51 @@ pub fn optimize(toks: &[Token]) -> Vec<Token> {
}
}

// Add
// [
// Add / Sub / Dup / Scan
} else if let Some(Token::Goto(there)) = next {
let next = toks.get(si + 2);

// [>
// Add / Dup
if let Some(Token::Inc(mul)) = next {
if let Some(Token::Goto(back)) = toks.get(si + 3) {
let next = toks.get(si + 4);

// [>+ ><
// Add
if *there == -back
&& matches!(toks.get(si + 4), Some(Token::Dec(1)))
&& matches!(next, Some(Token::Dec(1)))
&& matches!(toks.get(si + 5), Some(Token::RBrack(_)))
{
// [>+<-]
out.push(Token::Add(*there, *mul));

si += 6;
continue;

// [>+ ><
// Dup
} else if let Some(Token::Inc(mul2)) = next {
// [>+ >< +
if let Some(Token::Goto(bi)) = toks.get(si + 5) {
if *bi == -(there + back)
// [>+>+<<
&& matches!(toks.get(si + 6), Some(Token::Dec(1)))
// [>+>+<<-
&& matches!(toks.get(si + 7), Some(Token::RBrack(_)))
// [>+>+<<-]
{
out.push(Token::Dup(*there, *mul, *back, *mul2));

si += 8;
continue;
}
}
}
}

// Sub
} else if matches!(next, Some(Token::Dec(1))) {
if let Some(Token::Goto(back)) = toks.get(si + 3) {
if *there == -back
Expand All @@ -201,6 +264,8 @@ pub fn optimize(toks: &[Token]) -> Vec<Token> {
continue;
}
}

// Scan
} else if matches!(next, Some(Token::RBrack(_))) {
out.push(Token::Scan(*there));

Expand All @@ -210,17 +275,22 @@ pub fn optimize(toks: &[Token]) -> Vec<Token> {
}
}

if matches!(tok, Token::LBrack(_)) {
lbracks.push(out.len());
} else if matches!(tok, Token::RBrack(_)) {
let lb = lbracks
.pop()
.unwrap_or_else(|| err("invalid input", "unmatched closing bracket"));
out[lb] = Token::LBrack(out.len());
tok = Token::RBrack(lb);
} else if matches!(tok, Token::Goto(0)) {
si += 1;
continue;
match tok {
Token::LBrack(_) => lbracks.push(out.len()),
Token::RBrack(_) => {
let lb = lbracks
.pop()
.unwrap_or_else(|| err("invalid input", "unmatched closing bracket"));
out[lb] = Token::LBrack(out.len());
tok = Token::RBrack(lb);
}

Token::Goto(0) | Token::Inc(0) | Token::Dec(0) => {
si += 1;
continue;
}

_ => {}
}

out.push(tok);
Expand Down Expand Up @@ -255,6 +325,15 @@ impl Display for Token {
"+".repeat(*mul as usize)
),
Token::Sub(i) => write!(f, "[{}-{}-]", left_right(*i), left_right(-i)),
Token::Dup(i1, mul1, i2, mul2) => write!(
f,
"[-{}{}{}{}{}]",
left_right(*i1),
"+".repeat(*mul1 as usize),
left_right(*i2),
"+".repeat(*mul2 as usize),
left_right(-(i1 + i2)),
),
Token::Scan(i) => write!(f, "[{}]", left_right(*i)),

#[cfg(any(debug_assertions, feature = "debug"))]
Expand Down

0 comments on commit 7a8cfed

Please sign in to comment.