feat(generator): re-implement generator 🚀
ci/woodpecker/push/lint Pipeline was successful Details
ci/woodpecker/pr/lint Pipeline was successful Details
ci/woodpecker/push/build Pipeline was successful Details
ci/woodpecker/pr/build Pipeline was successful Details

This commit is contained in:
Aire-One 2022-10-22 15:08:33 +02:00
parent d8cb5918a7
commit ddf9858aa0
4 changed files with 75 additions and 131 deletions

View File

@ -1,66 +1,50 @@
local Function_Info = require "entities.Function_Info"
local List = require "pl.List"
local utils = require "utils" local utils = require "utils"
local template = require "pl.template" local template = require "pl.template"
-- Refactor scraper code to use pl.List objects local snippets = {}
local function join<T>(arr: { string }, delim: string): string
function snippets.indent(str: string, level: number): string
level = level or 1
local ret = "" local ret = ""
for i, t in ipairs(arr) do for line in str:gmatch("[^\n]+") do
ret = ret .. t ret = ret .. string.rep(" ", level * 3) .. line .. "\n"
if i < #arr then
ret = ret .. delim
end
end end
return ret return ret
end end
local record Anonymous_Function_Parameter_Record function snippets.render_typed_variable(name: string, types: List<string>): string
name: string local tmpl =
type: { string } [[$(name): $(types)]]
end
local record Anonymous_Function_Record local tmpl_args = {
name: string name = name,
parameters: { Anonymous_Function_Parameter_Record } types = types:concat(", "),
returns: { string }
end
local snippets = {
Anonymous_Function_Parameter_Record = Anonymous_Function_Parameter_Record,
Anonymous_Function_Record = Anonymous_Function_Record,
} }
function snippets.types_list(types: { string }): string return utils.do_or_fail(template.substitute, tmpl, tmpl_args)
return join(types, ", ")
end
function snippets.anonymous_function(item: Anonymous_Function_Record): string
local parameters_string = ""
if item.parameters then
for i, param in ipairs(item.parameters) do
parameters_string = parameters_string .. param.name
local types = "any"
if param.type then
types = snippets.types_list(param.type)
end
parameters_string = parameters_string .. ": " .. types
if i < #item.parameters then
parameters_string = parameters_string .. ", "
end
end
end
local returns_string = ""
if item.returns then
returns_string = snippets.types_list(item.returns)
end end
function snippets.render_anonymous_function_signature(item: Function_Info.Function_Info): string
local tmpl = local tmpl =
[[function($(parameters_string))$(#returns_string > 0 and (": " .. returns_string))]] [[$(function_name): function($(function_parameter))$(#function_return > 0 and (": " .. function_return))]]
return utils.do_or_fail(template.substitute, tmpl, { local tmpl_args = {
parameters_string = parameters_string, function_name = item.name,
returns_string = returns_string, function_parameter = item.parameters:map(function(param: Function_Info.Parameter): string
}) return snippets.render_typed_variable(param.name, List({param.type})) -- TODO : add support for multiple types
end):concat(", "),
function_return = item.return_types:concat(", "),
}
return utils.do_or_fail(template.substitute, tmpl, tmpl_args)
end
function snippets.render_record_functions(items: List<Function_Info.Function_Info>): string
return items:map(function(item: Function_Info.Function_Info): string
return snippets.render_anonymous_function_signature(item)
end):concat("\n")
end end
return snippets return snippets

View File

@ -1,64 +1,42 @@
local file = require "pl.file" local Module_Doc = require "entities.Module_Doc"
local template = require "pl.template" local template = require "pl.template"
local path = require "pl.path"
local utils = require "utils" local utils = require "utils"
local snippets = require "generator.snippets" local snippets = require "generator.snippets"
local tmpl = (function(mod: string): string -- The long therm goal is to have so many `snippets.render_*` functions that
local package_path = utils.do_or_fail(path.package_path, mod) -- we can render the whole file with the smallest template possible.
local package_dir = path.dirname(package_path) local tmpl = [[
return utils.do_or_fail(file.read, package_dir .. "/template.tl.tmpl", false) -- Auto generated file (Do not manually edit this file!)
end)(...)
# if module.signals then
local enum signals
# for _, signal in ipairs(module.signals) do
"$(signal.name)"
# end
end
# end -- /signals
local record $(mod_name)
# if #module.methods then
-- Object methods
$(snippets.indent(snippets.render_record_functions(module.methods)))
# end -- /methods
end
return $(mod_name)
]]
local module = {} local module = {}
local record Generate_Teal_Data_Record function module.generate_teal(mod: string, data: Module_Doc.Module_Doc): string
section: string local tmpl_args = {
items: { snippets.Anonymous_Function_Record }
end
function module.generate_teal(data: { Generate_Teal_Data_Record }): string
-- TODO : add the required modules to the generated code
-- TODO : replace this with a proper way to get the module name (will also probably need the module path)
local record Module_Data_Record
name: string
static_functions: { snippets.Anonymous_Function_Record }
constructors: { snippets.Anonymous_Function_Record }
methods: { string }
properties: { snippets.Anonymous_Function_Record }
signals: { snippets.Anonymous_Function_Record }
end
local module_data: Module_Data_Record = { name = "module_name" }
for _, item in ipairs(data) do
if item.section == "Static functions" then
-- TODO
module_data.static_functions = item.items
elseif item.section == "Constructors" then
-- TODO
module_data.constructors = item.items
elseif item.section == "Object properties" then
-- TODO
module_data.properties = item.items
elseif item.section == "Object methods" then
module_data.methods = {}
-- TODO : add the self parameter
-- TODO : define overrides to use the signal type in connect/emit functions
for _, i in ipairs(item.items) do
table.insert(
module_data.methods,
i.name .. ": " .. snippets.anonymous_function(i)
)
end
elseif item.section == "Signals" then
module_data.signals = item.items
end
end
local env = {
ipairs = ipairs, ipairs = ipairs,
module = module_data, mod_name = mod,
module = data,
snippets = snippets,
} }
return utils.do_or_fail(template.substitute, tmpl, env) return utils.do_or_fail(template.substitute, tmpl, tmpl_args)
end end
return module return module

View File

@ -1,20 +0,0 @@
-- Auto generated file (Do not manually edit this file!)
# if module.signals then
local enum signals
# for _, signal in ipairs(module.signals) do
"$(signal.name)"
# end
end
# end -- /signals
local record $(module.name)
# if module.methods then
-- Object methods
# for _, method in ipairs(module.methods) do
$(method)
# end
# end -- /methods
end
return $(module.name)

View File

@ -1,9 +1,10 @@
local crawler = require "crawler" local crawler = require "crawler"
local filesystem = require "filesystem"
local inspect = require "inspect" local inspect = require "inspect"
local log = require "logger" local log = require "logger"
local properties = require "properties" local properties = require "properties"
local scraper = require "scraper" local scraper = require "scraper"
-- local generator = require "generator" local generator = require "generator"
log:info( log:info(
inspect { message = "Start extraction", base_url = properties.base_url } inspect { message = "Start extraction", base_url = properties.base_url }
@ -28,12 +29,13 @@ log:info(inspect { modules_found = #module_infos })
local html = local html =
crawler.fetch(properties.base_url .. "/widgets/wibox.widget.textbox.html") crawler.fetch(properties.base_url .. "/widgets/wibox.widget.textbox.html")
local module_doc = scraper.module_doc.get_doc_from_page(html) local module_doc = scraper.module_doc.get_doc_from_page(html)
log:info(inspect { module_doc = module_doc }) -- log:info(inspect { module_doc = module_doc })
-- local items = scraper.get_doc_from_page(page) -- local items = scraper.get_doc_from_page(page)
-- log:info(inspect { items }) -- log:info(inspect { items })
-- generator.write( local mod = "textbox"
-- generator.generate_teal(items), filesystem.file_writer.write(
-- properties.out_directory .. "/test.tl" generator.teal_type_definitions.generate_teal(mod, module_doc),
-- ) properties.out_directory .. "/" .. mod .. ".d.tl"
)