📜 ⬆️ ⬇️

We write the interpreter Brainfuck on Lua

Lua Logo
Each programmer during his life has time to learn many languages, in several of them he specializes and continues to work for a long time, while the rest pass by. For different reasons. Is it worth spending time learning new languages, when you have already decided on the area in which you will work? Personally, I am sure that it is worth it, although, perhaps, many will say that fundamental knowledge in computer science is important, and in what language to write code is not critical. In essence, it is. Nevertheless, learning languages ​​is interesting and useful.

Lua. A brief history of the language.

The language Lua ([lua], port. “Moon”) takes its origin in a relatively distant year 1993. It was created by Roberto Ierusalimschy, Luiz Henrique de Figueiredo and Waldemar Celes, while members of the Computer Graphics Technology Development Group (Tecgraf) of the Catholic Universite of Rio de Janeiro (Pontifical) University of Rio de Janeiro) in Brazil. This is a scripting language that combines the properties of imperative and functional languages ​​and has object-oriented properties. Experienced by the influence of Scheme, SNOBOL, JavaScript, C / C ++ and others. The result is an embeddable, easily extensible scripting language with a simple syntax.
Over the years, Lua has gained popularity precisely as an embedded language: many programs, but even more games use it. For example, Vim (from version 7.3), World of Warcraft, Ragnarok Online and many others

A little about the language

It is best written here www.lua.ru/doc (rus) and here www.lua.org/manual/5.1 (eng)

Install Lua

Download Lua here luabinaries.sourceforge.net/download.html
Under Linux (although there are already three versions in the Ubuntu 10.04 repository)
sudo apt-get install lua5.1 sudo apt-get install lua50 sudo apt-get install lua40 

')
Either compile from source (the name of the lua5.1 package was not at all obvious, so I had to compile)
 cd /tmp wget http://www.lua.org/ftp/lua-5.1.4.tar.gz tar -xf lua-5.1.4.tar.gz cd lua-5.1.4 sudo apt-get install build-essential libreadline5-dev make linux test sudo checkinstall --fstrans=no --install=no --pkgname=lua --pkgversion "5.1.4" --default sudo dpkg -i lua_5.1.4-1_i386.deb lua -v >>> Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio 


Great, now you can start having fun.

Hello World!

How to start learning a language? With Hello world! not interested. Let's write an interpreter. There is such a wonderful language Brainfuck, very simple and very interesting. Helps stretch the brain.

We set the task:


Brainfuck Description

In the “classic” Brainfuck described by Urban Muller, the cell size is one byte, the number of cells is 30,000, input / output is byte-wise, the number of instructions is 8 pcs. Below is a brief description:



We write

Let's start small: create a directory for work, a file brainfuck.lua in it, make it executable

 #!/usr/bin/env lua -- Lua Brainfuck Interpreter Brainfuck = { -- validate source -- Return 1 if closing bracket(s) missing. -- Return 2 if opening bracket(s) missing. -- Return 0 otherwise. validate = function (self, source) return 0 end, -- debug function showError = function (self, errorCode) end, -- brainfuck function brainfuck = function (self, source) end, } 


Also create a file hello.b (the code on the brainfuck. Displays Hello World! To the screen. Needed for tests)
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

Well, now everything is ready.

1. Reading brainfuck code from file.

Let our interpreter execute code from a file whose name is passed on the command line.
./brainfuck.lua hello.b
The documentation will tell us that Lua puts the parameters in the arg array.

 -- start here if arg[1] then -- read source from file in arg[1] source = io.input(arg[1]):read("*a") -- get error code (0 == no error) errorCode = Brainfuck:validate(source) -- if no error run source else show error if errorCode == 0 then Brainfuck:brainfuck(source) else Brainfuck:showError(errorCode) end else print("Usage: ./brainfuck.lua script") Brainfuck:showError(3) end 


2. Basic code validation


 -- validate source -- Return 1 if closing bracket(s) missing. -- Return 2 if opening bracket(s) missing. -- Return 0 otherwise. validate = function (self, source) local i, errorCode, l = 0, 0, 0 for i = 1, string.len(source), 1 do -- [ 91 if string.byte(source, i) == 91 then l = l + 1 -- ] 93 elseif string.byte(source, i) == 93 then l = l - 1 if l < 0 then return 2 end end end if l > 0 then return 1 elseif l < 0 then return 2 else return 0 end end, -- debug function showError = function (self, errorCode) if errorCode == 1 then print("Error: Closing bracket(s) missing.") elseif errorCode == 2 then print("Error: Opening bracket(s) missing.") elseif errorCode == 3 then print("Error: No source file.") else print("Error: Unknown error code.") end end, 


3. Execution of Brainfuck Code


 -- brainfuck function brainfuck = function (self, source) -- memSize: Brainfuck memory size (30k) -- maxVal: Max memory value (255) byte -- mem: Memory table (array) -- pointer: default 0 -- l: default 0. braket level counter local memSize, maxVal, mem, pointer, l = 30000, 255, {}, 0, 0 -- clear memory for i = 0, memSize, 1 do mem[i] = 0 end -- execute program i = 0 while i <= string.len(source) do i = i + 1 -- + 43 C eqv ++(*p); if string.byte(source, i) == 43 then if mem[pointer] < maxVal then mem[pointer] = mem[pointer] + 1 end -- - 45 C eqv --(*p); elseif string.byte(source, i) == 45 then if mem[pointer] > 0 then mem[pointer] = mem[pointer] - 1 end -- , 44 C eqv *p = getchar(); elseif string.byte(source, i) == 44 then mem[pointer] = string.byte(io.stdin:read('*l'), 1) -- . 46 C eqv putchar(*p); elseif string.byte(source, i) == 46 then io.write(string.char(mem[pointer])) -- < 60 C eqv --p; elseif string.byte(source, i) == 60 then pointer = pointer - 1 if pointer < 0 then pointer = 0 end -- > 62 C eqv ++p; elseif string.byte(source, i) == 62 then pointer = pointer + 1 if pointer > memSize then pointer = memSize end -- [ 91 C eqv while (*p) { elseif string.byte(source, i) == 91 then if mem[pointer] == 0 then while (string.byte(source, i) ~= 93) or (l > 0) do i = i + 1 if string.byte(source, i) == 91 then l = l + 1 end if string.byte(source, i) == 93 then l = l - 1 end end end -- ] 93 C eqv } elseif string.byte(source, i) == 93 then if mem[pointer] ~= 0 then while (string.byte(source, i) ~= 91) or (l > 0) do i = i - 1 if string.byte(source, i) == 91 then l = l - 1 end if string.byte(source, i) == 93 then l = l + 1 end end end else -- print("Unknown symbol") -- return end -- print("Debug: l="..l.." cmd="..string.char(string.byte(source, i))) end end, 


Finished version

Is done. Now you can run the example and make sure that everything works. As you can see, Lua is quite suitable for standalone use)

I apologize for the lack of indenting. Lost when backlit.
I did not find a blog about Lua, so I will post it in Abnormal programming.
If articles about Lua are interesting to the community, I can write more

Useful literature

Source: https://habr.com/ru/post/112919/


All Articles