@@ -27,18 +27,17 @@ fn BFState.new(program string) &BFState {
2727}
2828
2929// show the current state of an BF interpreter. Useful for debugging.
30- fn (state &BFState) show () {
31- println ('PC: ${state .pc }' )
32- println ('Address: ${state .address }' )
30+ fn (state &BFState) show (suffix string ) {
3331 mut max_non_zero_address := - 1
3432 for i := state.memory.len - 1 ; i > = 0 ; i-- {
3533 if state.memory[i] != 0 {
3634 max_non_zero_address = i
3735 break
3836 }
3937 }
40- println ('Memory: ${state .memory #[0 ..max_non_zero_address + 1 ]}' )
41- println ('Memory[Address]: ${state .memory #[state .address ..state .address + 1 ]}' )
38+ println ('PC: ${state .pc :04 } | Address: ${state .address :04 } | Memory: ${state .memory #[0 ..
39+ max_non_zero_address + 1 ]:- 40 s } | Memory[Address]: ${state .memory #[state .address ..
40+ state .address + 1 ]:- 10 s } | ${suffix }' )
4241}
4342
4443// find_matching_pairs fills in the `targets` mapping for all pairs of `[` and `]`,
@@ -81,10 +80,15 @@ fn (state &BFState) panic_for_bracket(b1 rune, b2 rune) {
8180}
8281
8382fn (mut state BFState) run () ? {
83+ mut i := 0
8484 // the BF interpreter starts here:
8585 for state.pc < state.program.len {
8686 // get the current program character (corresponding to our program counter), and interpret it according to BF's rules:
87- match state.program[state.pc] {
87+ instruction := state.program[state.pc]
88+ $if trace_execution ? {
89+ state.show ('instruction ${i :08 }: ${instruction :02 x }, ${rune (instruction )}' )
90+ }
91+ match instruction {
8892 `>` {
8993 state.address++ // increment the address
9094 }
@@ -118,13 +122,14 @@ fn (mut state BFState) run() ? {
118122 }
119123 }
120124 `#` {
121- state.show ()
125+ state.show ('#' )
122126 }
123127 else {
124128 // The interpreter should ignore characters that are not part of the language.
125129 // I.e. they are treated like programmer comments.
126130 }
127131 }
132+ i++
128133 // increment the program counter to go to the next instruction
129134 state.pc++
130135 // go back to the line `for state.pc < state.program.len {`
@@ -134,7 +139,7 @@ fn (mut state BFState) run() ? {
134139@[noreturn]
135140fn show_usage () {
136141 eprintln ('you need to supply a brainfuck program/expression as a string argument,' )
137- eprintln ('or filename.b, if it is located in a file (note the `.b` extension).' )
142+ eprintln ('or filename.b, if it is located in a file (note the `.b` or `.bf` extension).' )
138143 exit (1 ) // exit with non-zero exit code if there is no program to run
139144}
140145
@@ -143,7 +148,7 @@ fn main() {
143148 show_usage ()
144149 }
145150 mut program := os.args[1 ] // our program is fed in as a string
146- if program.ends_with ('.b' ) {
151+ if program.ends_with ('.b' ) || program. ends_with ( '.bf' ) {
147152 program = os.read_file (program) or {
148153 eprintln ('error reading file ${program }: ${err }' )
149154 show_usage ()
@@ -154,6 +159,6 @@ fn main() {
154159 state.run ()
155160
156161 if show_state {
157- state.show ()
162+ state.show ('FINAL' )
158163 }
159164}
0 commit comments