feat(generator): base implem for `generate_teal`
ci/woodpecker/pr/docker-build Pipeline was successful Details
ci/woodpecker/pr/lint Pipeline was successful Details
ci/woodpecker/pr/build Pipeline was successful Details
ci/woodpecker/pr/test Pipeline was successful Details

This commit is contained in:
Aire-One 2023-04-16 22:15:47 +02:00
parent 896c7f2f04
commit 592e62d6fa
3 changed files with 117 additions and 47 deletions

View File

@ -58,6 +58,11 @@ local function create_node(token: Node.Token, name: string): Node
return node
end
local function iter_children(node: Node): function(): integer, Node
return ipairs(node.children)
end
return {
create_node = create_node,
iter_children = iter_children,
}

View File

@ -1,56 +1,116 @@
local Module_Doc = require "entity.Module_Doc"
local template = require "pl.template"
local utils = require "utils"
local snippets = require "generator.snippets"
local ast = require "ast"
local logger = require "logger"
local type Node = require "types.Node"
-- The long therm goal is to have so many `snippets.render_*` functions that
-- we can render the whole file with the smallest template possible.
local tmpl = [[
-- Auto generated file (Do not manually edit this file!)
local log = logger.log("scraper")
# if module.requires:len() ~= 0 then
$(snippets.render_requires(module.requires))
# end -- /requires
local record $(module.record_name)
# if #module.signals ~= 0 then
$(snippets.indent(snippets.render_enum("Signal", module.signals)))
# end -- /signals
# if #module.methods ~= 0 then
-- Object methods
$(snippets.indent(snippets.render_record_functions(module.methods)))
# end -- /methods
# if #module.properties ~= 0 then
-- Object properties
$(snippets.indent(snippets.render_record_properties(module.properties)))
# end -- /properties
# if #module.constructors ~= 0 then
-- Constructors
$(snippets.indent(snippets.render_record_functions(module.constructors)))
# end -- /constructors
# if #module.static_functions ~= 0 then
-- Static functions
$(snippets.indent(snippets.render_record_functions(module.static_functions)))
# end -- /static_functions
local function concatenate_strings(strings: { string }): string
local result = ""
for _, str in ipairs(strings) do
result = result .. str
end
return result
end
return $(module.record_name)
]]
local function render_types(types: { string }): string
if not types or #types == 0 then
return ""
end
local module = {}
return ": " .. concatenate_strings(types)
end
function module.generate_teal(data: Module_Doc.Module_Doc): string
local tmpl_args = {
ipairs = ipairs,
module = data,
snippets = snippets,
local record Node_Generator_Function
on_node: function(node: Node): string
before_node: nil | function(node: Node): string
after_node: nil | function(node: Node): string
end
-- pre-declare functions to prevent forward reference errors
local generate_teal: function(node: Node): string
local generate_children: function(node: Node): string
local node_generator <total>: { Node.Token : Node_Generator_Function } = {
["module"] = {
before_node = function(node: Node): string
return "-- This file was auto-generated.\n\nlocal record " .. node.name .. "\n"
end,
on_node = function(node: Node): string
return generate_children(node)
end,
after_node = function(node: Node): string
return "end\n\nreturn " .. node.name
end,
},
["record"] = {
before_node = function(node: Node): string
return "local record " .. node.name
end,
on_node = function(node: Node): string
return generate_children(node)
end,
after_node = function(): string
return "end"
end,
},
["enum"] = {
before_node = function(node: Node): string
return "enum " .. node.name .. "\n"
end,
on_node = function(node: Node): string
return generate_children(node)
end,
after_node = function(): string
return "end"
end,
},
["identifier"] = {
on_node = function(node: Node): string
return "\"" .. node.name .. "\""
end,
},
["variable"] = {
on_node = function(node: Node): string
return node.name .. render_types(node.types)
end,
},
["function"] = {
on_node = function(node: Node): string
local args = {}
for _, parameter in ipairs(node.parameters) do
table.insert(args, generate_teal(parameter))
end
return node.name .. ": function(" .. table.concat(args, ", ") .. ")" .. render_types(node.return_types)
end,
},
["metamethod"] = {
on_node = function(): string
log:warn("Metamethods are not supported yet")
end,
}
return utils.do_or_fail(template.substitute, tmpl, tmpl_args)
}
function generate_teal(node: Node): string
local generator = node_generator[node.token]
local generated = ""
if generator.before_node then
generated = (generator.before_node as function(node: Node): string)(node)
end
generated = generated .. generator.on_node(node)
if generator.after_node then
generated = generated .. (generator.after_node as function(node: Node): string)(node)
end
return generated
end
return module
function generate_children(node: Node): string
local generated = ""
for _, child in ast.iter_children(node) do
generated = generated .. generate_teal(child) .. "\n"
end
return generated
end
return {
generate_teal = generate_teal,
}

View File

@ -142,7 +142,7 @@ end
-- end
local module_ast, other_nodes = scraper.module_doc.get_doc_from_page(
crawler.fetch(property.base_url .. "/widgets/wibox.widget.imagebox.html"),
crawler.fetch(property.base_url .. "/core_components/tag.html"),
"awful.tag"
)
@ -150,3 +150,8 @@ log:info(logger.message_with_metadata("Finished", {
module_ast = module_ast,
other_nodes = other_nodes,
}))
filesystem.file_writer.write(
generator.teal_type_definitions.generate_teal(module_ast),
property.out_directory .. "/" .. "generated_from_ast" .. ".d.tl"
)