Anuncios Google

Intérprete Brainfuck en Lua [Aporte]

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:

  • Creo que debería escribir Brain*uck dado a que hay palabras ofensivas por medio, pero el nombre del lenguaje de programación es Brainfuck.
  • El programa tal y como está no os funcionará en vuestra PSP ni mucho menos, es algo así como un framework o librería con el que podeis experimentar.
  • Yo he llamado BFX al intérprete dado a que es un lenguaje que estoy desarrollando, basado en BF pero añadiendo funciones a mayores.

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!


Anuncios Google