SlopScupper
00 crowd

go2bf

Compile Go to Brainfuck!
Open repo on GitHubgithub.com/itchyny/go2bf
Go · ★ 21 · 0 forks · MIT · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other
listed 10 hours ago by itchyny · last checked 1 hour ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-09-11: A compiler from Go to Brainfuck that even runs Reversi; the owner writes "With Claude, I built the entire compiler in just three days". 21 stars; MIT license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as itchyny. There's no account to make: SlopScupper only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
Compile Go to Brainfuck!
topics
brainfuck
created
2026-04-17 · pushed 1 month ago · 83 commits · 1 contributor
release
v0.1.2 · 2026-07-28
languages
Go 100%Makefile 0%
paperwork
licensereadme 42% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 10 hours ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
language (detected)
gomakefile
topic (detected)
brainfuck
license (detected)
mit

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: A compiler from Go to Brainfuck that even runs Reversi; the owner writes "With Claude, I built the entire compiler in just three days". It carries the MIT license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

go2bf

CI Status MIT License release

Compile Go to Brainfuck!

Examples

FizzBuzz

Uses for loops, if-else chains, and modulo.

package main

func main() {
    for i := byte(1); i <= 100; i++ {
        if i%15 == 0 {
            print("FizzBuzz")
        } else if i%3 == 0 {
            print("Fizz")
        } else if i%5 == 0 {
            print("Buzz")
        } else {
            print(i)
        }
        println()
    }
}

Compile to Brainfuck:

 $ go2bf fizzbuzz.go
>>>>>>>>+>>>>>>>>+>>>>>>>>+>>>>>>>>+[>>>>>>>>]>>>[>>>]+++[<+++++>-]<[>+<-[>>>+<<
<-]>>>]<<[<<<]<<<<<<<<[<<<<<<<<]>[-]>>>>>[-]>[-]<<<<<<[>>>>>+>+<<<<<<-]>>>>>>[<<
<<<<+>>>>>>-]<<<<<[-]+>>>>[<<<<[-]>>>>[-]][-]>>[>>>>>>>>]>>>>>>>[-]<[<<<]<<<<<<<
...

Compile and run:

 $ go2bf run fizzbuzz.go
1
2
Fizz
4
Buzz
Fizz
...
Recursive Fibonacci

Uses recursion returning a byte.

package main

func fib(n byte) byte {
    if n <= 1 {
        return n
    }
    return fib(n-1) + fib(n-2)
}

func main() {
    for i := byte(1); i <= 10; i++ {
        print("fib(")
        print(i)
        print(") = ")
        println(fib(i))
    }
}
 $ go2bf run fibonacci.go
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
Factorial numbers

Uses recursion with 32-bit integers and type conversion.

package main

func factorial(n byte) uint32 {
    if n == 0 {
        return 1
    }
    return uint32(n) * factorial(n-1)
}

func main() {
    for i := byte(0); i <= 12; i++ {
        print(i)
        print("! = ")
        println(factorial(i))
    }
}
 $ go2bf run factorial.go
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
Structs with methods

Uses structs, value-receiver methods, and composite literals.

package main

type Point struct {
    x byte
    y byte
}

func (p Point) add(q Point) Point {
    return Point{x: p.x + q.x, y: p.y + q.y}
}

func main() {
    a := Point{x: 1, y: 2}
    b := Point{x: 3, y: 4}
    c := a.add(b)
    print("(")
    print(c.x)
    print(", ")
    print(c.y)
    println(")")
}
 $ go2bf run point.go
(4, 6)
Roman numerals

Uses a global array and string concatenation.

package main

type RomanRule struct {
    value  uint16
    symbol string
}

var rules = [...]RomanRule{
    {value: 1000, symbol: "M"},
    {value: 900, symbol: "CM"},
    {value: 500, symbol: "D"},
    {value: 400, symbol: "CD"},
    {value: 100, symbol: "C"},
    {value: 90, symbol: "XC"},
    {value: 50, symbol: "L"},
    {value: 40, symbol: "XL"},
    {value: 10, symbol: "X"},
    {value: 9, symbol: "IX"},
    {value: 5, symbol: "V"},
    {value: 4, symbol: "IV"},
    {value: 1, symbol: "I"},
}

func main() {
    for _, n := range [...]uint16{
        1, 4, 13, 49, 99, 133, 444, 1999, 3888,
    } {
        k, s := n, ""
        for _, r := range rules {
            for k >= r.value {
                s += r.symbol
                k -= r.value
            }
        }
        println(n, "=", s)
    }
}
 $ go2bf run roman.go
1 = I
4 = IV
13 = XIII
49 = XLIX
99 = XCIX
133 = CXXXIII
444 = CDXLIV
1999 = MCMXCIX
3888 = MMMDCCCLXXXVIII
Prime numbers

Uses a slice that grows with append and range over it.

package main

func main() {
    var primes []byte
    for n := byte(2); n < 100; n++ {
        prime := byte(1)
        for _, p := range primes {
            if p*p > n {
                break
            }
            if n%p == 0 {
                prime = 0
                break
            }
        }
        if prime == 1 {
            primes = append(primes, n)
        }
    }
    for i, p := range primes {
        if i > 0 {
            print(" ")
        }
        print(p)
    }
    println()
}
 $ go2bf run primes.go
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Reversi

You can play Reversi written in Brainfuck!

 $ go2bf run testdata/reversi.go
  ABCDEFGH
1 ........
2 ........
3 ...*....
4 ..*OX...
5 ...XO*..
6 ....*...
7 ........
8 ........
X:2 O:2
X move: D3

  ABCDEFGH
1 ........
2 ........
3 ..*X*...
4 ...XX...
5 ..*XO...
6 ........
7 ........
8 ........
X:4 O:1
O move: E3
...

Installation

go install github.com/itchyny/go2bf@latest

Usage

# Compile Go to Brainfuck
go2bf source.go > output.bf

# Compile and run
go2bf run source.go

# Compile multiple files
go2bf run main.go helper.go

# Compile from stdin
echo 'package main ...' | go2bf -

# Compile with debug comments
go2bf -debug source.go

How it works

The compiler pipeline:

  1. Parse - Uses Go's go/ast parser to parse the source code
  2. Analyze - Builds call graph, detects recursion and tail calls
  3. Lower - Converts AST to a structured IR (intermediate representation)
  4. Optimize IR - Constant folding, delta conversion, fresh-zero elimination
  5. Generate - Converts IR to Brainfuck using a register-cache CPU model with optimized register allocation and stack traffic reduction
  6. Optimize BF - Peephole optimization on the generated Brainfuck code (merging, cancellation, dead loop elimination)

Execution model

The generated Brainfuck uses a CPU-like execution model:

  • 5 registers at positions 1,2,4,5,7 interleaved with algorithm temps for neighbor optimization
  • Register cache with LRU eviction (consecutive operations on same variables stay in registers, dead temporaries skipped)
  • Stride-8 highway markers at positions 8, 16, 24, 32 for fast tape navigation
  • Phase temps at fixed tape positions 25-39 for recursive dispatch computation
  • Stride-3 stack with guard/value/zero cells for variable storage
  • Counter-walk technique for navigating to stack slots via the zero column
  • Breadcrumb technique for far stack access (guard=0 marks target slot)
  • Phase dispatch loop for general recursion with dynamic stack frames

Supported Go features

Types and operators

  • byte (uint8, 0-255), uint16 (0-65535), uint32 (0-4294967295), uint64 (0-2^64-1)
  • Arithmetic: +, -, *, /, %, ++, --, +=, -=, *=, /=, %=, unary +, -
  • Bitwise: &, |, ^, &^, <<, >>, ^x, &=, |=, ^=, <<=, >>=
  • Comparison: ==, !=, <, >, <=, >= (including array and struct equality)
  • Logical: &&, ||, ! (0 is false, nonzero is true)
  • Type conversion: byte(expr), uintN(expr), string(byte) in print/println
  • Constants: const n = 10, const nl = '\n', const msg = "hello", const blocks with iota
  • Top-level var declarations of byte, uintN, arrays, structs, and slices.

Control flow

  • if, else if, else statements
  • for loops with break and continue, including labeled break and continue to escape or resume an outer loop
  • switch statement on byte, uintN values (including multiple values per case, default, fallthrough, and break to exit a case early)

Functions

  • Parameters, return values, multiple return values, named return values
  • Multi-return tuples of any type combination (func f() (P, P), func f() ([3]byte, [3]byte), func f() (string, byte))
  • Multi-return spread into another call: f(g()) when g's returns match f's parameters positionally
  • Methods on value and pointer receivers (func (p P) m(), func (p *P) m())
  • Methods on struct literals (P{x: 10}.method())
  • Method chaining including pointer-returning methods (s.push(1).push(2).pop()) and explicit address-of receivers ((&b).method())
  • Tail-call recursion optimization
  • General recursion (via stack-based dispatch) including nested recursive calls (e.g., Ackermann function)
  • Multi-byte (uint16/uint32) parameters, locals, and return values in recursive functions; binary recursion (fib, Pascal's triangle via choose) and accumulator patterns
  • defer for function calls (LIFO order; not supported inside loops)
  • init() function, inlined before main (one per package; multiple inits not yet supported)

Arrays

  • [N]byte, [N]uintN, [N]Point, [N][M]byte, [N][M]uintN, [N][M]Point, [N][M][K]byte
  • Constant and variable indexing
  • Composite literals: [N]byte{...}, [N]byte{0: v}
  • len(array), cap(array), for i, v := range a
  • Copy assignment, a[i]++, a[i] += v
  • Pass to and return from functions

Structs

  • Top-level and function-local type definitions
  • Fields: byte, uintN, struct, *Struct, array, nested array, string, []byte, []uintN, []Struct, [][]byte types
  • Nested struct array fields ([N][M]Inner)
  • Field access, nested field access (p.a.x, arr[i].inner.x)
  • Composite literals, copy assignment
  • p.x++, p.x += v, a[i].x = v, s.vals[i] = v, s.ps[i].x = v (struct slice field write through index)
  • Chained field operations on indexed elements: read/write through a[i].inner.x, arr[i].inner = Inner{...}, parallel swap a[i].x, a[i].y = a[i].y, a[i].x, and multi-return a[i].x, a[i].y = f()
  • Composite equality and copy at indexed elements (a[i] == a[j], a[i] == Point{...}, a[j] = a[i])
  • Return composite by value from indexed base (return a[i], return s[i] for struct slices)
  • Pass to and return from functions
  • Value and pointer receivers (func (v T) m(), func (p *T) m())
  • Struct embedding with field and method promotion, including multi-level embedding and promotion through pointers and indexing.

Slices

  • []byte, []uintN, []Point, [][N]byte, [][]byte, []*byte, []*Point
  • Composite literals: []byte{1, 2, 3}, []byte{2: 5, 4: 9}, []Point{Point{1, 2}, Point{3, 4}}
  • make([]byte, n), make([]Point, n, cap)
  • Indexing: s[i], s[i].x for struct slices
  • len(s), cap(s), for _, v := range s
  • append(s, v), append(s, a, b, c), append(s, t...) with automatic reallocation, including a string source (append(b, str...))
  • copy(dst, src), clear(s), including copying a string into a byte slice (copy(b, str))
  • Array slicing: a[i:j], a[i:], a[:j], a[i:j:k], a[:]
  • Reslicing: s[i:j], s[i:], s[:j], s[i:j:k]
  • s == nil, s != nil comparison
  • Copy assignment, s[i]++, s[i].x++
  • Pass to and return from functions
  • Backed by a dynamic allocator with in-place growth when possible (old arrays not freed otherwise)

Strings

  • String variables backed by []byte slices: s := "hello", var s string, s = "world", print(s), println(s)
  • len(s), s[i], s[i:j], s[i:], s[:j]
  • Range over string (by byte, not rune): for i, b := range s
  • Equality, lexicographic ordering: s == t, s != t, s < t, s > t, s <= t, s >= t
  • Concatenation s + t and compound assign s += t
  • Conversions: []byte(s), string(bs), string(byte('A'))
  • Function parameters and returns, including named string returns (func g() (msg string)) and multi-return tuples containing strings (func f() (string, byte))
  • defer println(s + "!"), switch s { case "test": ... }
  • String constants and concatenations of them in const blocks
  • String fields in structs, struct equality compares string content
  • Slices and arrays of strings or byte slices: []string{"a", "b"}, [N]string{"a", "b", "c"}, [N][]byte{{'h','i'}, {'b','y','e'}}, make([]string, n)

Pointers

  • *byte, *uintN pointers: &x, *p, *p = v, *p++, *p--
  • &myStruct, &myArray, &Point{x: 1, y: 2}
  • &a[i], &s[i] -- address of array/slice elements
  • &p.field -- address of struct field, including through indexed bases and chains (&arr[i].x, &arr[i].inner.x, &arr[i].xs[1])
  • ptr.x read/write for struct pointers (ptr := &myStruct)
  • (*ptr).x read/write (equivalent via auto-deref)
  • q := pp pointer alias (both observe the same target)
  • q := *pp full-struct copy through a pointer
  • ptr[i] read/write, ptr[i][j] read/write for array pointers
  • ptr[i].x read/write for array-of-structs pointers
  • ptr.data[i] read/write for struct-with-array pointers, including multi-byte (pp.x[i] = uint16(...)), struct (pp.items[i].field), and nested-array (pp.grid[i][j] for a [N][M]T field) element types
  • Pointer-typed struct fields (type Outer struct { p *Inner }): out.p.v read/write follows the field's pointer to the target
  • len(ptr), len(*ptr), cap(ptr) for array pointers
  • ptr == nil, ptr != nil comparison
  • Typed pointer parameters: func f(p *[N]byte), func f(p *[N][M]byte), func f(p *Point), func f(p *uintN)
  • Pass pointers to functions for by-reference semantics

Built-in functions

  • print, println -- decimal output, string literals, multi-return expansion
  • len(x), cap(x) -- arrays, slices, pointers
  • make([]T, n), make([]T, n, cap) -- slices of byte, struct, or array types
  • append(s, v), append(s, a, b, c), append(s, t...) -- with automatic reallocation; t may be a string when s is a byte slice
  • copy(dst, src) -- copy slice elements; src may be a string when dst is a byte slice
  • clear(s) -- zero all slice elements
  • min(a, b, ...), max(a, b, ...) -- variadic

go2bf extensions:

  • putchar(byte) -- raw byte output
  • getchar() -- read a byte from stdin

Limitations

  • No import statements.
  • No int, signed integer, floating-point number types.
  • No maps, interfaces, channels, closures, function pointers.
  • Array nesting up to [N][M][K]byte. [N][M][K][L]byte, [N][M][K]Point, [N][M][K]uintN are not supported.
  • Slice nesting up to [][]byte. [][][]byt

Read the rest on GitHub

Scan report · 2026-09-11
  • Prohibited terms or links — profanity in body/README
  • Repository eligibility
  • slopscore.md paperwork
  • Content policy
  • Risk review

0 comments

log in to comment.

report this listinglog in to report