Puesto a que el foro de programación lo veía un tanto parado decidí postear un intérprete del lenguaje Brainfuck, que yo mismo he programado en Lua.
Unas cosillas antes de nada:
Otra cosa, este intérprete os va a funcionar en Lua nativo, tanto para PC como para Android con SL4A, y sí, lo he probado. Además, es facilmente portable a PSP por si alguien se anima, eso si, tened cuidado por como manejo los archivos de salida io.stdout y io.stdin, puede que tengais que emular las funciones write y read en estos archivos usando algo así como un archivo virtual (Yo es lo que hice y funciona bien).
Vamos al grano:
El lenguaje es algo complejo (por no decir mucho) a la hora de usar para programar, en cambio solo tiene 8 instrucciones, todas de un Byte, muy faciles de memorizar. en Wikipedia os podreis hacer una idea de la dificultad del lenguaje y de la programación de este, aquí teneis un Hello World de ejemplo:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Y sí, aunque algunos no os lo creais, ese código de ahí imprime en la pantalla Hello World!
El intérprete:
Puesto a que es un solo archivo, voy a poner la Source directamente:
--[[ BFX Fast interpreter. v0.1 BFX es un lenguaje de programación creado por Brais S. basado en Brainfuck y añadiendo más instrucciones. Esta versión del intérprete está en fase Alpha. ]] BFX__VERSION = "0.1 Alpha" BFX__CREATOR = "Brais S. / Theos @iRedHunter" BFX__VECTORSIZE = 30000 BFX__OUT = io.stdout BFX__IN = io.stdin BFX__ITER = 0 BFX__PROGMEM = "" BFX__SIZE = 0 BFX__POINTER = 1 BFX = {} BFX.progMem = {} BFX.addr = 1 BFX.instr = { add = string.byte("+"), sub = string.byte("-"), next = string.byte(">"), prev = string.byte("<"), startloop = string.byte("["), endloop = string.byte("]"), input = string.byte(","), output = string.byte(".") } BFX.vector = {0} function BFX.begin() BFX.vector = nil BFX__ITER = 0 collectgarbage("collect") BFX.vector = {0} end function BFX.setAddr(addr) BFX.addr = BFX.addr end function BFX.getAddr() return BFX.addr end function BFX.getIter() return BFX__ITER end BFX.Iter = BFX.getIter function BFX.setVector(addr,value) if type(value == "number") then BFX.vector[addr] = value elseif type(value == "string") then BFX.vector[addr] = value:sub(1,1) end end function BFX.getVector(addr) return BFX.vector[addr] end function BFX.VectorSize(size) if size then BFX__VECTORSIZE = size else return BFX__VECTORSIZE end end function BFX.VectorUsed() return #BFX.vector end function BFX.VectorFree() return BFX.VectorSize()-BFX.VectorUsed() end function BFX.setOut(fileOut) BFX__OUT = fileOut end function BFX.setIn(fileIn) BFX__IN = fileIn end function BFX.dumpVector(mode) mode = mode or "string" if mode == "table" then return BFX.vector elseif mode == "string" then local sVector = "" for i=1,BFX.VectorSize() do sVector = sVector .. string.char(BFX.getVector(i)) end return sVector elseif mode == "number" then local sVector = "" for i=1,BFX.VectorSize() do sVector = sVector .. " " .. BFX.getVector(i) end return sVector end end BFX.progMem.write = function(data) BFX__PROGMEM = BFX__PROGMEM .. data BFX__SIZE = #BFX__PROGMEM end BFX.progMem.read = function() BFX__SIZE = #BFX__PROGMEM return BFX__PROGMEM end BFX.progMem.clear = function() BFX__PROGMEM = "" collectgarbage("collect") BFX__SIZE = #BFX__PROGMEM end BFX.progMem.size = function() return #BFX__PROGMEM end BFX.getPointer = function() return BFX__POINTER end BFX.setPointer = function(value) BFX__POINTER = value end function BFX.run() BFX__ITER = BFX__ITER+1 local cmd = BFX__PROGMEM:byte(BFX.addr) if cmd == BFX.instr.add then -- + BFX.vector[BFX__POINTER] = BFX.vector[BFX__POINTER]+1 if BFX.vector[BFX__POINTER] == 256 then BFX.vector[BFX__POINTER] = 0 end elseif cmd == BFX.instr.sub then -- - BFX.vector[BFX__POINTER] = BFX.vector[BFX__POINTER]-1 if BFX.vector[BFX__POINTER] == -1 then BFX.vector[BFX__POINTER] = 255 end elseif cmd == BFX.instr.next then -- > BFX__POINTER = BFX__POINTER+1 if(BFX.vector[BFX__POINTER] == nil ) then BFX.vector[BFX__POINTER] = 0 end if(#BFX.vector == BFX__VECTORSIZE) then return "Error. Overflow: Out of memory" end elseif cmd == BFX.instr.prev then -- < BFX__POINTER = BFX__POINTER-1 if BFX__POINTER == 0 then return "Error. Underflow: Out of memory" end elseif cmd == BFX.instr.input then -- , local entry = BFX__IN:read(1) if entry == nil then BFX.vector[BFX__POINTER] = 0 else entry = string.byte(entry) if entry > 255 then entry = 255 elseif entry < 0 then entry = 0 end BFX.vector[BFX__POINTER] = entry end elseif cmd == BFX.instr.output then -- . BFX__OUT:write(string.char(BFX.vector[BFX__POINTER])) elseif cmd == BFX.instr.startloop and BFX.vector[BFX__POINTER] == 0 then local descent = 1 repeat BFX.addr = BFX.addr+1 if BFX.addr > BFX.progMem.size() then return "Error. Syntax: Unmatched [" end cmd = BFX__PROGMEM:byte(BFX.addr) if cmd == BFX.instr.startloop then descent = descent+1 elseif cmd == BFX.instr.endloop then descent = descent-1 end until descent == 0 elseif cmd == BFX.instr.endloop and BFX.vector[BFX__POINTER] ~= 0 then local descent = 1 repeat BFX.addr = BFX.addr-1 if BFX.addr == 0 then return "Error. Syntax: Unmatched ]" end cmd = BFX__PROGMEM:byte(BFX.addr) if cmd == BFX.instr.endloop then descent = descent+1 elseif cmd == BFX.instr.startloop then descent = descent-1 end until descent == 0 end BFX.addr = BFX.addr+1 end
Y esto es todo, ya sabeis, yo os dejo el código, a partir de ahí podeis hacer lo que querais con el, ¡esto es Open Source chicos!
PD: Las funciones son muy faciles de entender cuando se entiende como funciona BF, así que no es necesario que añada una documentación.
Saludos!