v / examples
Raw file | 66 loc (60 sloc) | 1.9 KB | Latest commit hash 017ace6ea
1import os
2
3fn main() {
4 if os.args.len < 2 {
5 eprintln('you need to supply a brainfuck program as a string argument')
6 exit(1) // exit with non-zero exit code if there is no program to run
7 }
8 program := os.args[1] // our program is fed in as a string
9
10 mut memory := []u8{len: 256} // we have 256 bytes of memory
11 mut address := u8(0) // as well as an 8-bit address register
12
13 mut stack := []int{} // our stack does not need a maximum length
14
15 mut program_counter := 0 // program counter
16
17 // interpreter starts here
18 for program_counter < program.len {
19 // we look at what the current character our program counter is seeing
20 match program[program_counter] {
21 `>` {
22 address++ // increment the address
23 }
24 `<` {
25 address-- // decrement the address
26 }
27 `+` {
28 memory[address]++ // increment the value at the address
29 }
30 `-` {
31 memory[address]-- // decrement the value at the address
32 }
33 `.` {
34 print(memory[address].ascii_str()) // print the value at the address
35 }
36 `,` {
37 input := os.input_opt('') or { '' } // read value and account for errors
38 memory[address] = input[0] // this is so we can ignore newlines
39 // because strings are 0-terminated, it also gives us a default value for free!
40 }
41 `[` {
42 stack << program_counter // add loop start address to the call stack
43 }
44 `]` {
45 if memory[address] != 0 {
46 // set the program counter to the last loop start
47 // so it jumps back and loops again
48 program_counter = stack[stack.len - 1]
49 } else {
50 // otherwise remove the address from the stack and continue
51 stack.pop()
52 }
53 }
54 else {
55 // the interpreter should ignore characters that are not part of the language
56 }
57 }
58 // increment the program counter to go to the next instruction
59 program_counter++
60 // back to line 20!
61 }
62
63 // print the state of the interpreter at the end
64 println('Address: ${address}')
65 println('Memory: ${memory}')
66}