BrainForth
Jump to navigation
Jump to search
BrainForth is an esoteric programing language created by User:Binarycat in 2020 that combines the tape and minimal instruction set of brainfuck with Forth's word system.
There are 11 predefined words, the eight original brainfuck instructions, ':' and ';' (used for defining words), and '?' (skip next instr if current cell is 0 (I'm not super sure about this one, it may get removed from the language at some point)). The file extention is ".bfth".
Go Implementation
package main import ( "strings" "bufio" "os" ) var ( inDefMode bool inCondMode bool newWordName string newWordBody []string tape [200]byte ptr int = 100 words map[string]func() src = make([]string,0,100) srcPos int stdin = bufio.NewReader(os.Stdin) stdout = bufio.NewWriter(os.Stdout) ) func init() { words = map[string]func(){ "+": inc, "-": dec, "<": shiftl, ">": shiftr, ",": readc, ".": writec, "[": lbracket, "]": rbracket, "?": enterCondMode, ":": startNewWord, ";": endNewWord, } } func main() { srcRdr := openSrcFile() for ln, _, err := srcRdr.ReadLine();err == nil;ln, _, err = srcRdr.ReadLine() { wds := strings.Fields(string(ln)) for _, wd := range wds { src = append(src,string(wd)) } } run(src) stdout.Flush() } func run(src []string) { for srcPos < len(src) { runWord(src[srcPos]) srcPos++ } } func runWord(wd string) { if inDefMode && wd != ";" { if newWordName == "" { newWordName = wd } else { newWordBody = append(newWordBody,wd) } } else if inCondMode && tape[ptr] != 0 { return } else { f, ok := words[wd] if !ok {panic("unknow word "+wd)} f() } } func lbracket() { if tape[ptr] == 0 { jumpr() } } func rbracket() { if tape[ptr] != 0 { jumpl() } } func jump(dir int) { srcPos += dir bDepth := dir for bDepth != 0 { switch src[srcPos] { case "]": bDepth-- case "[": bDepth++ } srcPos += dir } } func jumpr() { jump(1) } func jumpl() { jump(-1) } func inc() { tape[ptr]++ } func dec() { tape[ptr]-- } func shiftl() { ptr-- } func shiftr() { ptr++ } func readc() { c, err := stdin.ReadByte() if err != nil { panic(err) } tape[ptr] = c } func writec() { err := stdout.WriteByte(tape[ptr]) if err != nil { panic(err) } } func startNewWord() { enterDefMode() newWordBody = newWordBody[:0] newWordName = "" } func endNewWord() { exitDefMode() words[newWordName] = comWord(newWordBody) } func enterDefMode() { inDefMode = true } func exitDefMode() { inDefMode = false } func comWord(wds []string) func() { wdsCp := make([]string,len(wds)) copy(wdsCp,wds) return func() { oldPos := srcPos oldSrc := src src = wdsCp srcPos = 0 run(wdsCp) srcPos = oldPos src = oldSrc } } func enterCondMode() { inCondMode = true } func openSrcFile() *bufio.Reader { if len(os.Args) == 0 || os.Args[0] == "-" { return bufio.NewReader(os.Stdin) } f, err := os.Open(os.Args[1]) if err != nil {panic(err)} return bufio.NewReader(f) }
Example Programs
hello.bfth:
: PRINT [ . > ] ; : +8 + + + + + + + + ; : +16 +8 +8 ; : +32 +16 +16 ; : +64 +32 +32 ; : a +64 +32 + ; : h a +8 - ; : e a + + + + ; : l h + + + + ; : o l + + + ; h > e > l > l > o [ < ] > PRINT