12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- -- Brainfuck interpreter in Lua using a [] cache.
- -- This is public domain.
- local src, err = io.open(arg[1], "r")
- if src == nil then
- print("Error opening file " .. arg[1] .. ": " .. err)
- os.exit(1)
- end
- local code = src:read("*a")
- src:close()
- src = nil
- local ip = 1
- local dp = 1
- local mem = {0}
- local codelen = string.len(code)
- local jumpcache = {}
- local commands =
- {
- add = string.byte("+"),
- sub = string.byte("-"),
- next = string.byte(">"),
- prev = string.byte("<"),
- startloop = string.byte("["),
- endloop = string.byte("]"),
- input = string.byte(","),
- output = string.byte(".")
- }
- while ip <= codelen do
- local cmd = string.byte(code, ip)
- if cmd == commands.add then
- mem[dp] = mem[dp] + 1
- if mem[dp] == 256 then mem[dp] = 0 end
- elseif cmd == commands.sub then
- mem[dp] = mem[dp] - 1
- if mem[dp] == -1 then mem[dp] = 255 end
- elseif cmd == commands.next then
- dp = dp + 1
- if mem[dp] == nil then mem[dp] = 0 end
- elseif cmd == commands.prev then
- dp = dp - 1
- if dp == 0 then
- print("Underflow error at " .. ip)
- os.exit(1)
- end
- elseif cmd == commands.input then
- local entry = io.stdin:read(1)
- if entry == nil then
- mem[dp] = 0 -- end of file
- else
- entry = string.byte(entry)
- if entry > 255 then entry = 255
- elseif entry < 0 then entry = 0 end
- mem[dp] = entry
- end
- elseif cmd == commands.output then
- io.stdout:write(string.char(mem[dp]))
- elseif cmd == commands.startloop and mem[dp] == 0 then
- if jumpcache[ip] ~= nil then ip = jumpcache[ip]
- else
- local descent, oldip = 1, ip
- repeat
- ip = ip + 1
- if ip > codelen then
- print("Unmatched [")
- os.exit(1)
- end
- cmd = string.byte(code, ip)
- if cmd == commands.startloop then descent = descent + 1
- elseif cmd == commands.endloop then descent = descent - 1 end
- until descent == 0
- jumpcache[oldip] = ip
- end
- elseif cmd == commands.endloop and mem[dp] ~= 0 then
- if jumpcache[ip] ~= nil then ip = jumpcache[ip]
- else
- local descent, oldip = 1, ip
- repeat
- ip = ip - 1
- if ip == 0 then
- print("Unmatched ]")
- os.exit(1)
- end
- cmd = string.byte(code, ip)
- if cmd == commands.startloop then descent = descent - 1
- elseif cmd == commands.endloop then descent = descent + 1 end
- until descent == 0
- jumpcache[oldip] = ip
- end
- end
- ip = ip + 1
- end
|