bf

a simple toy bf compiler in hare, made for teaching!
Log | Files | Refs

commit 443781e92502d53fafb64a6914b66f221e9c3bf6
parent 830dead3769cf6c3a2c37e2700818cb4666d875f
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Tue, 27 Jan 2026 21:34:14 +0000

started interpreter

Diffstat:
D.gitignore | 1-
MMakefile | 5+++--
Abf | 0
Abrainf/parse.ha | 29+++++++++++++++++++++++++++++
Abrainf/run.ha | 25+++++++++++++++++++++++++
Abrainf/types.ha | 1+
Acmd/bf/main.ha | 27+++++++++++++++++++++++++++
7 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +0,0 @@ -bf diff --git a/Makefile b/Makefile @@ -12,6 +12,9 @@ HARE_SOURCES != find . -name '*.ha' all: bf +bf: $(HARE_SOURCES) + $(HARE) build $(HAREFLAGS) -o $@ cmd/$@/ + clean: rm -f bf @@ -23,5 +26,3 @@ check: .PHONY: all check clean install uninstall -bf: $(HARE_SOURCES) - $(HARE) build $(HAREFLAGS) -o $@ cmd/$@/ diff --git a/bf b/bf Binary files differ. diff --git a/brainf/parse.ha b/brainf/parse.ha @@ -0,0 +1,29 @@ +use io; +use fmt; +use bufio; + +export fn load(h: io::handle, inblock: bool = false) (*block | io::EOF | io::error) = { + let insts: [](u8 | *block) = []; + + for (true) { + let c = match (bufio::read_byte(h)?) { + case let c: u8 => yield c; + case io::EOF => + if (inblock) fmt::fatal("unexpected EOF"); + return alloc(insts)!: *block; + }; + + switch (c) { + case '+', '-', '>', '<', '.', ',' => append(insts, c)!; + case '[' => + let nested = load(h, true)! as *block; + append(insts, nested)!; + case ']' => return alloc(insts)!: *block; + case => fmt::fatalf("unexpected token type {}", c: rune); + }; + }; +}; + +export fn finish(b: *block) void = { + free(b); +}; diff --git a/brainf/run.ha b/brainf/run.ha @@ -0,0 +1,25 @@ +use fmt; + +export fn run(b: *block, arr: *[]u8, ptr: i32 = 0) void = { + for (let inst .. b) { + match (inst) { + case let nested: *block => + for (arr[ptr] != 0) + run(nested, arr, ptr); + case let c: u8 => + switch (c: rune) { + case '+' => arr[ptr] += 1; + case '-' => arr[ptr] -= 1; + case '>' => + ptr += 1; + if (ptr > (len(arr) - 1): i32) ptr = 0; + case '<' => + ptr -= 1; + if (ptr < 0) ptr = (len(arr) - 1): i32; + case ',' => arr[ptr] = 0; // TODO stdin + case '.' => fmt::print(arr[ptr]: rune)!; + case => abort(); + }; + }; + }; +}; diff --git a/brainf/types.ha b/brainf/types.ha @@ -0,0 +1 @@ +export type block = [](u8 | *block); diff --git a/cmd/bf/main.ha b/cmd/bf/main.ha @@ -0,0 +1,27 @@ +use fmt; +use io; +use bufio; +use memio; +use strings; + +use brainf; + +fn printblock(b: *brainf::block) void = { + for (let inst .. b) { + match (inst) { + case let c: u8 => fmt::print(c: rune)!; + case let b: *brainf::block => + fmt::println()!; + printblock(b); + fmt::println()!; + }; + }; +}; + +export fn main() void = { + let in = &memio::fixed(strings::toutf8("+[[->]-[-<]>-]>.>>>>.<<<<-.>>-.>.<<.>>>>-.<<<<<++.>>++.")).stream; + let b = brainf::load(in) as *brainf::block; + + let arr: []u8 = alloc([0...], 30000)!; + brainf::run(b, &arr); +};