From 35549c21bc017eb1250d7e48fddcbd6899dc8f3e Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 18 Sep 2022 01:20:17 +0200 Subject: [PATCH] A brainf**k example. --- lib/std/io.c3 | 7 +++ resources/examples/brainfk.c3 | 86 +++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 resources/examples/brainfk.c3 diff --git a/lib/std/io.c3 b/lib/std/io.c3 index c1b714adb..36b4e4b36 100644 --- a/lib/std/io.c3 +++ b/lib/std/io.c3 @@ -185,6 +185,13 @@ fn String File.getline(File* file, Allocator* allocator = mem::current_allocator return s; } +fn char! File.getc(File* file) +{ + int c = libc::fgetc(file.file); + if (c == -1) return IoError.FILE_EOF!; + return (char)c; +} + /** * @param [&in] file * @require file.file `File must be initialized` diff --git a/resources/examples/brainfk.c3 b/resources/examples/brainfk.c3 new file mode 100644 index 000000000..b74881cc1 --- /dev/null +++ b/resources/examples/brainfk.c3 @@ -0,0 +1,86 @@ +// #target: macos-x64 +module brainfk; +import std::io; + +const BF_MEM = 30000; +char[BF_MEM] memory; + +fault InterpretError +{ + INTEPRET_FAILED +} + +fn void! print_error(usize pos, char[] err) +{ + io::printfln("Error at %s: %s", pos, err); + return InterpretError.INTEPRET_FAILED!; +} + +fn void! brainf(char[] program) +{ + usize sp = 0; + usize mem = 0; + while (sp < program.len) + { + char c = program[sp++]; + switch (c) + { + case '<': + if (!mem) return print_error(sp, "Memory underflow"); + mem--; + case '>': + if (mem == BF_MEM - 1) return print_error(sp, "Memory overflow"); + mem++; + case '+': + memory[mem]++; + case '-': + memory[mem]--; + case '.': + io::putchar(memory[mem]); + io::stdout().flush(); + case ',': + memory[mem] = io::stdin().getc()!!; + case '[': + usize indent = 1; + if (memory[mem]) continue; + usize start = sp - 1; + while (indent) + { + if (sp == program.len) return print_error(start, "No matching ']'"); + switch (program[sp++]) + { + case ']': indent--; + case '[': indent++; + default: break; + } + } + case ']': + if (!memory[mem]) continue; + usize start = sp--; + usize indent = 1; + while (indent) + { + if (!sp) return print_error(start, "No matching '['"); + switch (program[--sp]) + { + case ']': indent++; + case '[': indent--; + default: break; + } + } + sp++; + default: + break; + } + } +} +fn void! main() +{ + char[] program = ` + ++++[>+++++<-]>[<+++++>-]+<+[ + >[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+ + >>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<] + <<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<- + ]`; + brainf(program)?; +} \ No newline at end of file