123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- local preamble = [[
- declare extern type userdata with end
- declare extern type lightuserdata with end
- declare extern type quaternion with
- x: number
- y: number
- z: number
- w: number
- end
- type Vec2 = {number}
- type Vec3 = {number} | vector
- type Vec4 = {number}
- type Quat = {number} | quaternion
- type Mat4 = {number}
- declare class Joint end
- declare class Shape end
- ]]
- local function genType(type, optional)
- local suffix = optional and '?' or ''
- if type == 'function' then -- TODO
- return '() -> ()' .. suffix
- elseif type == '*' then
- return 'any' .. suffix
- else
- return type:gsub('table', '{}') .. suffix
- end
- end
- local function genArguments(arguments, ismethod)
- local t = {}
- for _, arg in ipairs(arguments) do
- local name, type = arg.name, genType(arg.type, arg.default)
- if name:match('%.%.%.') then
- if ismethod then
- table.insert(t, '...: ' .. type)
- else
- table.insert(t, '...' .. type)
- end
- else
- table.insert(t, ('%s: %s'):format(name, type))
- end
- end
- return table.concat(t, ', ')
- end
- local function genReturns(returns)
- local t = {}
- for _, ret in ipairs(returns) do
- table.insert(t, genType(ret.type))
- end
- return table.concat(t, ', ')
- end
- local function genFunctionType(fn, variant)
- local args = genArguments(variant.arguments)
- local rets = genReturns(variant.returns)
- if #variant.returns == 1 then
- return ('(%s) -> %s'):format(args, rets)
- else
- return ('(%s) -> (%s)'):format(args, rets)
- end
- end
- local function genMethod(method, variant)
- local args = genArguments(variant.arguments, true)
- local rets = genReturns(variant.returns)
- if args == '' then
- args = 'self'
- else
- args = 'self, ' .. args
- end
- if #variant.returns > 1 then
- rets = (': (%s)'):format(rets)
- elseif #variant.returns == 1 then
- rets = ': ' .. rets
- end
- return (' function %s(%s)%s'):format(method.name, args, rets)
- end
- return function(api)
- local directory = lovr.filesystem.getSource() .. '/luau'
- if lovr.system.getOS() == 'Windows' then
- os.execute('mkdir ' .. directory:gsub('/', '\\'))
- else
- os.execute('mkdir -p ' .. directory)
- end
- local out = {}
- local function write(s, ...)
- table.insert(out, s:format(...))
- end
- write(preamble:gsub('^%s*', ''))
- write('\n')
- local function writeFunction(fn)
- if #fn.variants > 1 then
- write(' %s:\n', fn.name)
- for i, variant in ipairs(fn.variants) do
- write(' & (%s)%s\n', genFunctionType(fn, variant), i == #fn.variants and ',' or '')
- end
- else
- write(' %s: %s,\n', fn.name, genFunctionType(fn, fn.variants[1]))
- end
- end
- for _, module in ipairs(api.modules) do
- for _, enum in ipairs(module.enums) do
- write('type %s =\n', enum.name)
- for _, value in ipairs(enum.values) do
- write(' | %q\n', value.name)
- end
- write('\n')
- end
- local ignore = {
- Vec2 = true,
- Vec3 = true,
- Vec4 = true,
- Quat = true,
- Mat4 = true,
- Vectors = true
- }
- for _, object in ipairs(module.objects) do
- if not ignore[object.name] then
- write('declare class %s', object.name)
- if object.extends then
- write(' extends %s', object.extends)
- end
- write('\n')
- for _, method in ipairs(object.methods) do
- for _, variant in ipairs(method.variants) do
- write('%s\n', genMethod(method, variant))
- end
- end
- write('end\n\n')
- end
- end
- if module.name ~= 'lovr' and #module.functions > 0 then
- write('type %sModule = {\n', module.name:gsub('^%l', string.upper))
- for _, fn in ipairs(module.functions) do
- writeFunction(fn)
- end
- write('}\n\n')
- end
- end
- write('declare lovr: {\n')
- for _, module in ipairs(api.modules) do
- if module.name == 'lovr' then
- for _, fn in ipairs(module.functions) do
- writeFunction(fn)
- end
- end
- end
- write('\n')
- for _, callback in ipairs(api.callbacks) do
- writeFunction(callback)
- end
- write('\n')
- for _, module in ipairs(api.modules) do
- if module.name ~= 'lovr' and #module.functions > 0 then
- write(' %s: %sModule,\n', module.name, module.name:gsub('^%l', string.upper))
- end
- end
- write('}\n')
- local file = assert(io.open(directory .. '/lovr.d.luau', 'w'))
- file:write(table.concat(out):sub(1, -2))
- file:close()
- end
|