Last active
December 8, 2023 11:12
-
-
Save judofyr/7ed4b52af2107119d4cc1f989ca63201 to your computer and use it in GitHub Desktop.
Brainfuck macro in Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![recursion_limit="100"] | |
use std::io; | |
use std::io::{Write, Read}; | |
use std::num::Wrapping; | |
struct Tape<'a> { | |
stdin: &'a mut Read, | |
stdout: &'a mut Write, | |
data: Vec<Wrapping<u8>>, | |
pos: usize | |
} | |
impl<'a> Tape<'a> { | |
fn new(len: usize, stdin: &'a mut Read, stdout: &'a mut Write) -> Tape<'a> { | |
Tape { | |
data: vec![Wrapping(0); len], | |
pos: 0, | |
stdin: stdin, | |
stdout: stdout | |
} | |
} | |
fn dot(self: &mut Self) { | |
self.stdout.write(&[self.data[self.pos].0]).unwrap(); | |
} | |
fn comma(self: &mut Self) { | |
let mut data: [u8; 1] = [255]; // EOF is -1 | |
self.stdin.read(&mut data).unwrap(); | |
self.data[self.pos] = Wrapping(data[0]); | |
} | |
} | |
macro_rules! bf { | |
($var:ident; > $($rest:tt)*) => { $var.pos += 1; bf!($var; $($rest)*); }; | |
($var:ident; < $($rest:tt)*) => { $var.pos -= 1; bf!($var; $($rest)*); }; | |
($var:ident; + $($rest:tt)*) => { $var.data[$var.pos] += Wrapping(1); bf!($var; $($rest)*); }; | |
($var:ident; - $($rest:tt)*) => { $var.data[$var.pos] -= Wrapping(1); bf!($var; $($rest)*); }; | |
($var:ident; . $($rest:tt)*) => { $var.dot(); bf!($var; $($rest)*); }; | |
($var:ident; , $($rest:tt)*) => { $var.comma(); bf!($var; $($rest)*); }; | |
($var:ident; [ $($body:tt)* ] $($rest:tt)* ) => { | |
while $var.data[$var.pos].0 != 0 { | |
bf!($var; $($body)*); | |
}; | |
bf!($var; $($rest)*); | |
}; | |
($var:ident; .. $($rest:tt)*) => { bf!($var; . . $($rest)*); }; | |
($var:ident; >> $($rest:tt)*) => { bf!($var; > > $($rest)*); }; | |
($var:ident; << $($rest:tt)*) => { bf!($var; < < $($rest)*); }; | |
($var:ident; -> $($rest:tt)*) => { bf!($var; - > $($rest)*); }; | |
($var:ident; <- $($rest:tt)*) => { bf!($var; < - $($rest)*); }; | |
($var:ident;) => { }; | |
} | |
fn main() { | |
let mut out = io::stdout(); | |
let mut sin = io::stdin(); | |
// https://esolangs.org/wiki/Brainfuck#Cell_Size | |
{ | |
let mut t = Tape::new(5, &mut sin, &mut out); | |
bf! { t; | |
++++++++[>++++++++<-]>[<++++>-] | |
+<[>-< | |
[>++++<-]>[<++++++++>-]<[>++++++++<-] | |
+>[> | |
++++++++++[>+++++<-]>+.-.[-]< | |
<[-]<->] <[>> | |
+++++++[>+++++++<-]>.+++++.[-]< | |
<<-]] >[> | |
++++++++[>+++++++<-]>.[-]< | |
<-]< | |
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<. | |
>>.++.+++++++..<-.>>-. | |
}; | |
} | |
// https://esolangs.org/wiki/Brainfuck#Cat | |
{ | |
let mut t = Tape::new(1, &mut sin, &mut out); | |
bf! { t; ,+[-.,+] }; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment