@@ -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]:-40s} | Memory[Address]: ${state.memory#[state.address..
40+ state.address + 1]:-10s} | ${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:02x} , ${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