# BrainDead - A BrainF*ck interpreter for the ilo computer ~~~ c On startup this jumps into `main`, which sets up the repl and c begins accepting Brainf*ck source. : start i liju.... r main c `inc_pc` advances the program counter by one cell. : inc_pc i life.... r pc i liadli.. d 1 r pc i stre.... c `dec_pc` moves the program counter back by one cell. : dec_pc i life.... r pc i lisuli.. d 1 r pc i stre.... c `load_line` reads a line of input into `Program`, stopping at c EOF, newline, or carriage return. It then writes a 0 c terminator for `run_program`. : load_line i list.... r input_ptr : ll_loop i liio.... d 1 i duli.... d -1 i eqli.... r ll_done i cj...... i duli.... d 10 i eqli.... r ll_done i cj...... i duli.... d 13 i eqli.... r ll_done i cj...... i life.... r input_ptr i st...... i life.... r input_ptr i liadli.. d 1 r input_ptr i stliju.. r ll_loop : ll_done i drli.... d 0 i life.... r input_ptr i stre.... c `clear_tape` fills the Brainf*ck tape with zero values before c each run. : clear_tape i lili.... r Tape r clear_ptr i st...... : ct_loop i life.... r clear_ptr i liltli.. r TapeEnd r ct_body i cj...... i re...... : ct_body i lili.... d 0 r clear_ptr i fest.... i life.... r clear_ptr i liadli.. d 1 r clear_ptr i stliju.. r ct_loop c `scan_forward` skips ahead to the matching `]` when `[` is c reached with a zero cell. : scan_forward i lili.... d 1 r scan_depth i st...... : sf_loop i lica.... r inc_pc i lifefeli r pc r cmd i st...... i life.... r cmd i lieqli.. d 91 r sf_inc i cj...... i life.... r cmd i lieqli.. d 93 r sf_dec i cj...... : sf_check i life.... r scan_depth i ligtli.. d 0 r sf_loop i cj...... i lica.... r inc_pc i re...... : sf_inc i life.... r scan_depth i liadli.. d 1 r scan_depth i stliju.. r sf_check : sf_dec i life.... r scan_depth i lisuli.. d 1 r scan_depth i stliju.. r sf_check c `scan_backward` skips back to the matching `[` when `]` is c reached with a non-zero cell. : scan_backward i lili.... d 1 r scan_depth i st...... : sb_loop i lica.... r dec_pc i lifefeli r pc r cmd i st...... i life.... r cmd i lieqli.. d 93 r sb_inc i cj...... i life.... r cmd i lieqli.. d 91 r sb_dec i cj...... : sb_check i life.... r scan_depth i ligtli.. d 0 r sb_loop i cj...... i lica.... r inc_pc i re...... : sb_inc i life.... r scan_depth i liadli.. d 1 r scan_depth i stliju.. r sb_check : sb_dec i life.... r scan_depth i lisuli.. d 1 r scan_depth i stliju.. r sb_check c `run_program` initializes the program and data pointers, then c dispatches each Brainf*ck instruction until it reaches the 0 c terminator. : run_program i lili.... r Program r pc i stlili.. r Tape r dp i st...... : rp_loop i lifefeli r pc r cmd i st...... i life.... r cmd i lieqli.. d 0 r rp_done i cj...... i life.... r cmd i liltli.. d 43 r cmd_next i cj...... i life.... r cmd i ligtli.. d 93 r cmd_next i cj...... i life.... r cmd i lisu.... d 43 i liadfe.. r DispatchTable i list.... r dispatch_ptr i lifeju.. r dispatch_ptr : rp_done i re...... c `cmd_next` handles any ignored character by advancing to the c next instruction. : cmd_next i lica.... r inc_pc i liju.... r rp_loop c `cmd_right` moves the data pointer one cell to the right. : cmd_right i life.... r dp i liadli.. d 1 r dp i stlica.. r inc_pc i liju.... r rp_loop c `cmd_left` moves the data pointer one cell to the left. : cmd_left i life.... r dp i lisuli.. d 1 r dp i stlica.. r inc_pc i liju.... r rp_loop c `cmd_inc` increments the value at the current tape cell. : cmd_inc i life.... r dp i dufe.... i liadswst d 1 i lica.... r inc_pc i liju.... r rp_loop c `cmd_dec` decrements the value at the current tape cell. : cmd_dec i life.... r dp i dufe.... i lisuswst d 1 i lica.... r inc_pc i liju.... r rp_loop c `cmd_out` writes the current tape cell as a character. : cmd_out i lifefe.. r dp i liio.... d 0 i lica.... r inc_pc i liju.... r rp_loop c `cmd_in` reads one character into the current tape cell. If c input is exhausted, it stores 0 instead. : cmd_in i liio.... d 1 i duli.... d -1 i eqli.... r cmd_in_eof i cj...... i life.... r dp i stlica.. r inc_pc i liju.... r rp_loop : cmd_in_eof i drli.... d 0 i life.... r dp i stlica.. r inc_pc i liju.... r rp_loop c `cmd_open` handles `[`. If the current cell is zero, it skips c ahead to the matching `]`; otherwise it continues normally. : cmd_open i lifefe.. r dp i lieqli.. d 0 r open_skip i cj...... i lica.... r inc_pc i liju.... r rp_loop : open_skip i lica.... r scan_forward i liju.... r rp_loop c `cmd_close` handles `]`. If the current cell is non-zero, it c jumps back to the matching `[`; otherwise it continues. : cmd_close i lifefe.. r dp i lineli.. d 0 r close_back i cj...... i lica.... r inc_pc i liju.... r rp_loop : close_back i lica.... r scan_backward i liju.... r rp_loop c `main` provides a tiny repl for entering and running one line c of Brainf*ck at a time. : main : repl i liliio.. d 62 d 0 i liliio.. d 32 d 0 i lilica.. r Program r load_line i life.... r Program i lineli.. d 0 r run_once i cj...... i liio.... d 6 : run_once i lica.... r clear_tape i lica.... r run_program i liliio.. d 10 d 0 i liju.... r repl o 2000 c A few simple variables are used to hold the current program c state while a line is running. : pc d 0 : dp d 0 : cmd d 0 : scan_depth d 0 : input_ptr d 0 : clear_ptr d 0 : dispatch_ptr d 0 c `DispatchTable` maps ASCII values from `+` through `]` onto c the handlers used by `run_program`. : DispatchTable r cmd_inc r cmd_in r cmd_dec r cmd_out r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_left r cmd_next r cmd_right r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_next r cmd_open r cmd_next r cmd_close c `Program` stores the current line of Brainf*ck source, and c `Tape` holds the data cells it operates on. : Program * 4096 : Tape * 30000 : TapeEnd ~~~