Каждый программист за свою жизнь успевает изучить множество языков, в
нескольких из них специализируется и продолжает работать продолжительное
время, а остальные проходят мимо. По разным причинам. Стоит ли тратить
время на изучение новых языков, когда уже определился с областью в
которой будешь работать? Лично я уверен что стоит, хотя, быть может,
многие скажут что важны фундаментальные знания в computer science, а на
каком языке писать код не критично. В сущности так и есть. И тем не
менее изучать языки интересно и полезно.
Lua. Краткая история языка.
Своё начало язык Lua ([луа], порт. «луна») берёт в относительно далёком
1993 году. Его создали Роберто Иерусалимши (Roberto Ierusalimschy),
Луис Энрике де Фигуэйредо (Luiz Henrique de Figueiredo) и Вальдемар
Селес (Waldemar Celes), в то время члены группы разработки технологии
компьютерной графики (Tecgraf) Епископального католического университета
Рио-де-Жанейро (Pontifical Catholic University of Rio de Janeiro) в
Бразилии. Это скриптовый язык, сочетающий свойства императивных и
функциональных языков и обладающий объектно-ориентированными свойствами.
Испытал влияние Scheme, SNOBOL, JavaScript, C/C++ и других. В
результате получился встраиваемый, легко расширяемый скриптовый язык с
простым синтаксисом.
За годы существования Lua обрёл популярность именно как встраиваемый
язык: множество программ, но ещё больше игр используют его. Например Vim
(с версии 7.3), World of Warcraft, Ragnarok Online и многие другие
Скачать Lua можно тут luabinaries.sourceforge.net/download.html
Под Linux (правда в репозитории Ubuntu 10.04 есть аж три версии) sudo apt-get install lua5.1 sudo apt-get install lua50 sudo apt-get install lua40
Либо собрать из исходников (название пакета lua5.1 было совсем не очевидно, поэтому пришлось собрать) cd /tmp
wget 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
С чего начать изучение языка? С Hello world! не интересно. Давайте
напишем интерпретатор. Есть такой замечательный язык Brainfuck, очень
простой и очень интересный. Помогает размять мозг.
Ставим задачу:
Чтение brainfuck кода из файла
Базовая валидация кода
Исполнение Brainfuck кода
Описание Brainfuck
В «классическом» Brainfuck, описанном Урбаном Мюллером, размер ячейки —
один байт, количество ячеек 30 000, ввод/вывод происходит побайтово,
количество инструкций 8 шт. ниже краткое описание:
> перейти к следующей ячейке
< перейти к предыдущей ячейке
+ увеличить значение в текущей ячейке на 1
— уменьшить значение в текущей ячейке на 1
. напечатать значение из текущей ячейки
, ввести извне значение и сохранить в текущей ячейке
[ если значение текущей ячейки нуль, перейти вперёд по тексту программы
на ячейку, следующую за соответствующей ] (с учётом вложенности)
] если значение текущей ячейки не нуль, перейти назад по тексту программы на символ [ (с учётом вложенности)
Пишем
Начнём с малого: создадим каталог для работы, файл brainfuck.lua в нём, сделаем его исполняемым
#!/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,
}
Также создадим файл hello.b (код на brainfuck. выводит Hello World! на экран. нужен для тестов) ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
Ну, теперь всё готово.
1. Чтение brainfuck кода из файла.
Пусть наш интерпретатор выполняет код из файла имя которого передано в командной строке ./brainfuck.lua hello.b
Документация скажет нам что Lua помещает параметры в массив arg
-- 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. Базовая валидация кода
-- 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. Исполнение Brainfuck кода
-- 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
Готово. Теперь можно запустить пример и убедиться что всё работает. Как видите Lua вполне пригоден для standalone использования)
Прошу прощения за отсутствие отступов. Утеряны при подстветке.
Блога о Lua не нашел, поэтому размещу в Ненормальное программирование.
Если статьи о Lua интересны сообществу могу написать ещё