LINUX.ORG.RU

Luau - Lua с «батарейками», написанный на C++17

 ,


2

5

Luau (GitHub) - встраиваемый, Lua 5.1-совместимый (и частично с Lua 5.2-5.4), язык со следующими улучшениями (или «улучшениями»?):

function foo(x: number, y: string): boolean
    local k: string = y:rep(x)
    return k == "a"
end
type Point = { x: number, y: number }
type Array<T> = { [number]: T }
type Something = typeof(string.gmatch("", "%d"))
for k, v in {1, 4, 9} do
    assert(k * k == v)
end
  • улучшенный repl (используется C-альтернатива readline Isocline)
  • и другие изменения ;)

По соображениям безопасности отсутствуют io, os, package и debug.

(En|Destr)oy!

★★★★

Последнее исправление: dataman (всего исправлений: 2)

Составные операторы это конечно плюс. Но по остальному стоило ли делать форк языка? Хз даже.

Roblox

Аааа, понятно, они для себя и тех кто там миниигры клепает. Тада ладна.

Лучше бы luajit дофигачили до последней официальной lua. Все бы ручками хлопали и попками вертели

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

мне в lua не хватало u16string и regexp над ними, чтото велосипедил, где то у меня на lua валяется недоделанный редактор студия для андроид

anonymous2 ★★★★★
()
Ответ на: комментарий от anonymous2

Да, спасибо им. Но даже в их стандартной библиотеке по старинке используется lua.h. В дискуссиях я их спросил, можно ли (и как) использовать С++ API. Посмотрим, что ответят.

dataman ★★★★
() автор топика
Ответ на: комментарий от LINUX-ORG-RU

Язык создан как встраиваемый

И встраивают его теперь по поводу и без.

Поэтому «убогонький недоязычок» тут не к месту.

К месту. Одно другому не противоречит.

pr849
()
23 ноября 2022 г.

…cпустя некоторое время: добавлен JIT (компилировать с опцией -DLUAU_NATIVE=ON).

Для теста я выбрал scimark-fft.lua.

Lua enginerealusersys
lua 5.4.50m40.937s0m40.915s0m0.000s
luajit0m3.402s0m3.365s0m0.000s
luau0m35.659s0m35.563s0m0.004s
luau –codegen0m18.207s0m18.199s0m0.008s
dataman ★★★★
() автор топика
9 ноября 2023 г.
  • код переехал на https://github.com/luau-lang/luau;
  • удалена опция для компиляции с поддержкой генерации нативного кода – теперь она есть «из коробки» с ключом --codegen.

Новости: https://luau-lang.org/news

dataman ★★★★
() автор топика
Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от alysnix

У этого есть свои преимущества и это обычное поведение для большинства языков. Локальность по умолчанию только звучит хорошо, но на деле она сразу обязывает на просто написать print("hello") а ещё внести в локальную область этот самый print в lua стандартная база из коробки вшита в саму луа, её не надо подгружать и объявлять, она не иммутабельна и может быть изменена динамически или ещё до старта работы это следствие того что луа не существует сама по себе это всегда встраиваемый язык. Есть ещё разница в том как хранятся локальные и глобальные данные. Локальные быстрые ибо они переносятся на стек целиком либо прямым указателем без взятия хеша с глобальной таблички каждый раз при обращении. Поэтому есть ограничение на локальные переменные и функции. Отдельное слово global для явного указания что данные глобальны тоже лишь звучит красиво, а на деле костылей и подпорок не оберёшься из за побочных эффектов.

Идеального варианта нет, но явное указание локальности и «по умолчанию» глобальность дают хороший компромисс и большую гибкость, когда ты одновременно контролируешь и эффективное использование памяти и вычислительных ресурсов в зависимости в том что тебе более важно области видимости do...end никто не отменял как и в си {...} и в десяках других языков, опять же в них же всё всегда тоже глобально, а локальность компилируемой/интерпретируемой единицы есть сама по себе и лишь в отдельных случаях ты пишешь типа static int x = 5 если хочешь что-бы даже случайно через export кто не подхватил твои данные и другой компилируемой/интерпретируемой единицы (файла чаще всего, могут быть просто отдельные строки или замыкания или REPL)

Короче на деле не всё так просто и этот момент с local очень хорошо продуман и явно выбран учитывая как особенности языка, так и механизм взаимодействия с ним. У луа, лишь одна фундаментальная проблема это некая особенность работы таблиц и стандартных функций с nil и уже тридцатилетняя привычка людей считать nil ничем это родило кучу всякой фигни с которой нужно просто жить или выпускать lua-6.0 где поведение работы с nil будет изменено или будет новый тип nop который будет не просто типом который не является ни одним из базовых, а просто будет реально ничем, так как сейчас nil и реальное ничто это разные вещи которые вынуждают некоторые штуки в луа просто не делать. local в луа это здорово и хорошо.

Луа это часто просто гениальный баланс компромиссов, там любая закорючка обоснована. Но, некоторые вещи типа nil который тоже коспромисс вызывают спустя 30+ лет вопросы. Тогда это было экономией памяти и это правильно и это сейчас есть и это должно остаться, но вот в неекоторых случаях можно изменить поведение сохранив фичи и внеся ясность, просто тогда это не знали как сделать, а сейчас не делают потому что это будет тотальная несовместимость, просто весь прошлый код сломается разом. Для луа совместимость не так уж и важна в связи со спецификой языка, но тут будет прям конкретное такое эдакое. Так что Вавилонски решится на такое если пойдёт на пенсию наверное, хотяя…

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 2)
Ответ на: комментарий от Bad_ptr

Местами прикольно

  • циклы новые
  • очень много новых ключевых слов
  • составные операторы (приятно, но не фича)
  • десятка два вообще новых операторов заменяющих функции из math, приятно, но не фича
  • явное ООП (усложнение, class,new, конструкторы, деструкторы)
  • доп фомат вывода значений модное $"Age{number}" вместо конкатенации, но это можно сделать и в ванильке только вместо $ другой символ будет.
  • прикольная вещь с заморозкой таблиц, типа временный const
  • сишный тернарный оператор вместо/в дополнение ... = (...) and x or y

И так далее насколько я посмотрел большинство изменений изменение синтаксиса и сахар, не так то прикольно, там буквально сделали базу типа когда говорят, а чего нет вот этого которое есть в X а почему вот это так, а не как Y :D, без сомнения прикольно, но на главной написано Compatible with Lua 5.4 source & bytecode., а в документации на каждой третей странице The bytecode of this feature is not backwards-compatible with Lua.

Интересная реализация, но пользоваться я этим лично не буду =)

Ну и максимально тупой тест, но жиза. Загрузка и исполнение файла с 1000_000 строк вызова функции складывающей два числа и передающей следующей и так миллион раз. Значения и функция объявлены как локальные конечно.

dron@gnu:~/test$ lua bench.lua 
dron@gnu:~/test$ lua bench.lua 
------- Test 1000000 calls function --------
result:1000000
mem usage KB:83044.077148438
lua 5.1 >>> 77.564 ms
result:1000000
mem usage KB:110259.08691406
lua 5.2 >>> 74.223 ms
result:1000000
mem usage KB:91829.748046875
lua 5.3 >>> 65.794 ms
result:1000000
mem usage KB:77481.393554688
lua 5.4 >>> 52.523 ms
result:1000000
mem usage KB:82460.96484375
lua jit >>> 36.818 ms
result:1000000
mem usage KB:77488.41796875
lua pluto >>> 44.951 ms
dron@gnu:~/test$

Глянул по диагонали исходники, написано что C++ 86.0% C 8.5% ... но по взгляду на код всё должно быть наоборот, где там и зачем c++ непонятно =) Я так понял пилит там всё один человек, клёво, тут прям прицел писать большиие программы, в рамках написания сценариев, однострочников, внешней логики какой программы в целом программулек на +/-250 строчек преимуществ перед любой другой луа, как по мне, нету.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от dataman

Дольше всех собирается. Сразу упало на коде бенча, он же генератор самого себя, начальная lua любая лишь запускает бенч пропуская его один раз, вызывает другую версию луа передавая ему самого себя внутри каждый из них генерирует миллион строк кода, компилит через load() и уже его исполнение бенчится, так что каждая реализация бенчит себя чисто. Эти кульбиты чтобы не держать файл с миллионом строк. Ну так вот luau споткнулась ещё до этапа бенча самой себя а именно на этапе arg[2] == nil для неё пришлось написать ({...})[2] :D, но оно дальше сломалось так как аргументов командной строки оно оказывается не видит аргументами, а пробует исполнить их как файл, которого конечно нету ибо это аргумент для различия бенча как запускалки других бенчей и как бенча… Ну лавввдвнаа, сгенерирую мильён строк и запущу отдельно

dron@gnu:~/test$ du -h bb.lua #сгенерированный файл бенча 18 мегабайт
18M	bb.lua
dron@gnu:~/test$ time ./luau bb.lua 
result:1000000
mem usage KB:24465

real	0m10,507s
user	0m10,167s
sys	0m0,328s
dron@gnu:~/test$ time ./pluto bb.lua 
result:1000000
mem usage KB:24747.8828125

real	0m1,824s
user	0m1,568s
sys	0m0,252s
dron@gnu:~/test$ time lua5.1 bb.lua 
result:1000000
mem usage KB:39090.96875

real	0m0,707s
user	0m0,661s
sys	0m0,040s
dron@gnu:~/test$ time lua5.2 bb.lua 
result:1000000
mem usage KB:39086.662109375

real	0m0,786s
user	0m0,765s
sys	0m0,020s
dron@gnu:~/test$ time lua5.3 bb.lua 
result:1000000
mem usage KB:39087.045898438

real	0m0,647s
user	0m0,607s
sys	0m0,036s
dron@gnu:~/test$ time lua5.4 bb.lua 
result:1000000
mem usage KB:24740.921875

real	0m0,910s
user	0m0,899s
sys	0m0,005s
dron@gnu:~/test$ time luajit bb.lua 
result:1000000
mem usage KB:39098.686523438

real	0m0,578s
user	0m0,517s
sys	0m0,060s
dron@gnu:~/test$ 

А вот с jit они это того самого, перестарались. ибо с --codegen случается

[3424920.241522] traps: luau[2890510] trap invalid opcode ip:55d97f26b816 sp:7ffdaf683ad0 error:0 in luau[55d97f1d4000+185000]

Как хорошо что я ковыряю эмулятор опкодов opemu, с ним видно что

[3425127.307445] OPEMU:  ud2

UD2 опкод это вроде специальный дабы прервать работу программы железно и отпарсить трапсы ядра по этому поводу.

dron@gnu:~/test$ ./luau --codegen bb.lua 
Warning: Native code generation is not supported in current configuration
CodeGen/src/CodeGen.cpp(210): ASSERTION FAILED: isSupported()
Недопустимая инструкция
dron@gnu:~/test$ 

Если я правильно понял, --codegen сейчас по умолчанию в сборке, иначе вроде через ifdef и ключа бы такого не было. Тоесть not supported in current configuration это не конфигурация luau сборки это конфигурация моей машины? Нет всяких SSE4.1+ на которые полагется ихний и егошний :) jit и меня заранее шлют? Короче вот, как то так. Дальше лень копать и выяснять что конкретно не так. luau какая то проблемная для меня, ну вернее я не в курсе её особенностей.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от dataman

Страшно, но оно и не для показа было, на коленке каляк, коляк и всё.


local code_start, code_body, code_end =
[[
    local x,y = 0,1
    local function sum (x,y)
        return x + y
    end
]]
,
[[
    x = sum(x,y);
]],
[[
    print('result:'..x);
    print('mem usage KB:'..collectgarbage("count"))
    return x
]];


function new_stack ()
    return {""}
end

function add_string (stack, s)
    stack[#stack+1] = s;
      for i=#stack-1, 1, -1 do
      if #stack[i] > #stack[i+1] then
          break
      end
      stack[i] = stack[i] .. table.remove(stack);
    end
end
-- luau аргументы не видит
if arg[2] == 'run' then
local code = new_stack();

add_string(code,code_start);
for i = 1, 1000000 do
    add_string(code,code_body);
end
code[#code+1] = code_end;

local unpack = table.unpack or unpack;

local src = table.concat(code);

io.open('log','w'):write(src);

if load and loadstring then load = loadstring; end

local func,err = load(src);

if not func then
    print("[codeload error] "..err);
end

local s = os.clock() * 1000;
    local state, result = pcall(func);
local e = os.clock() * 1000;

if not state then
  print(result);
end
-- luau аргументы не видит
local name = arg[1] or arg[0];
print("lua "..name.. " >>> "..string.format("%0.3f",e-s).." ms");
end

if arg[2] == nil then
   print("------- Test 1000000 calls function --------")
   os.execute('lua5.1 bench.lua 5.1 run');
   os.execute('lua5.2 bench.lua 5.2 run');
   os.execute('lua5.3 bench.lua 5.3 run');
   os.execute('lua5.4 bench.lua 5.4 run');
   os.execute('luajit bench.lua jit run');
   os.execute('./pluto bench.lua pluto run'); --скомпилированный файлик должен
   os.execute('./luau bench.lua luau run');   --(и этот тоже) валяться в каталоге бенча
end

Запустить просто lua bench.lua для luau я писал полученный буфер в файл и сразу делал os.exit() и уже отдельно запускал.

  • lua bench.lua режим запуска всех бенчей
  • luaXYZ bench.lua XYZ run режим зупуска бенча той lua которая сейчас запускает бенч.

Для luau второй режим надо поправить, мне не хоца, проще записать в файл и от туда запускать.

Короче эта приблуда просто для теста больших файлов с сотнями тысяч вызовов чего-то, сейчас просто функция + сложения, а так перемножение таблиц через свойство метатаблю __add как GLSL типа матрицы калькулировать просто table = tableA * tableB где

tableA={
 xx,xy,xz,xw,
 yx,yy,yz,yw,
 zx,zy,zz,zw,
 wx,wy,wz,ww,
}
LINUX-ORG-RU ★★★★★
()