WIP: awesomerc.tl
should work #85
|
@ -211,4 +211,60 @@ describe("Teal type definition Printer", function()
|
||||||
|
|
||||||
return Timer
|
return Timer
|
||||||
]]))
|
]]))
|
||||||
|
|
||||||
|
it("should print a module with descendants", gen(
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {},
|
||||||
|
return_types = {},
|
||||||
|
name = "draw_to_cairo_context",
|
||||||
|
token = "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {},
|
||||||
|
return_types = {},
|
||||||
|
name = "imagebox",
|
||||||
|
metamethod = "__call",
|
||||||
|
token = "metamethod",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Imagebox",
|
||||||
|
module_path = "wibox.widget.imagebox",
|
||||||
|
dependencies = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Widget",
|
||||||
|
module_path = "wibox.widget",
|
||||||
|
dependencies = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
},
|
||||||
|
[[
|
||||||
|
-- This file was auto-generated.
|
||||||
|
local type Imagebox = require("wibox.widget.imagebox")
|
||||||
|
|
||||||
|
local record Widget
|
||||||
|
enum Signal
|
||||||
|
end
|
||||||
|
draw_to_cairo_context: function()
|
||||||
|
imagebox: Imagebox
|
||||||
|
end
|
||||||
|
|
||||||
|
return Widget
|
||||||
|
]]))
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -14,7 +14,7 @@ local basic_nodes <total>: { Node.Token : function(name: string, ...: any): Node
|
||||||
record = function(name: string, global: boolean): Node
|
record = function(name: string, global: boolean): Node
|
||||||
return {
|
return {
|
||||||
token = "record",
|
token = "record",
|
||||||
global = global,
|
global = global,
|
||||||
name = name,
|
name = name,
|
||||||
children = {},
|
children = {},
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,40 @@ local function create_node(token: Node.Token, name: string, ...: any): Node
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO : be less permissive and allow to merge only module ?
|
||||||
|
local function merge_nodes(node: Node, other: Node): Node
|
||||||
|
if node.token ~= other.token then
|
||||||
|
error("Cannot merge nodes of different types")
|
||||||
|
end
|
||||||
|
if node.name ~= other.name then
|
||||||
|
error("Cannot merge nodes of different names")
|
||||||
|
end
|
||||||
|
if node.module_path ~= other.module_path then
|
||||||
|
error("Cannot merge nodes of different module paths")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Basic fields should be overwritten by the new values
|
||||||
|
-- Teal wants us to use enums value to index a record, but it fails to understand my enum with
|
||||||
|
-- any other key from Node, so I'm forcing it to cooperate for now
|
||||||
|
local enum NodeField
|
||||||
|
"types"
|
||||||
|
end
|
||||||
|
for _, field in ipairs({"global", "types", "parameters", "return_types", "metamethod"}) do
|
||||||
|
local f = field as NodeField
|
||||||
|
node[f] = other[f]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Children should be merged
|
||||||
|
for _, child in ipairs(other.children) do
|
||||||
|
table.insert(node.children, child)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dependencies should be merged
|
||||||
|
for name, path in pairs(other.dependencies) do
|
||||||
|
node.dependencies[name] = path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function iter_children(node: Node): function(): integer, Node
|
local function iter_children(node: Node): function(): integer, Node
|
||||||
if node.children == nil then
|
if node.children == nil then
|
||||||
return function(): integer, Node end
|
return function(): integer, Node end
|
||||||
|
@ -77,6 +111,7 @@ local function iter_children(node: Node): function(): integer, Node
|
||||||
return ipairs(node.children)
|
return ipairs(node.children)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO : deprecate in favor of the iterator definition ?
|
||||||
local function in_order_visitor(node: Node, visitor: function(Node))
|
local function in_order_visitor(node: Node, visitor: function(Node))
|
||||||
for _, child in iter_children(node) do
|
for _, child in iter_children(node) do
|
||||||
in_order_visitor(child, visitor)
|
in_order_visitor(child, visitor)
|
||||||
|
@ -84,8 +119,28 @@ local function in_order_visitor(node: Node, visitor: function(Node))
|
||||||
visitor(node)
|
visitor(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function iter_in_order(node: Node): function(): Node
|
||||||
|
local stack: { Node } = {}
|
||||||
|
|
||||||
|
local function traverse(n: Node)
|
||||||
|
for _, child in iter_children(n) do
|
||||||
|
traverse(child)
|
||||||
|
end
|
||||||
|
table.insert(stack, n)
|
||||||
|
end
|
||||||
|
traverse(node)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
return function(): Node
|
||||||
|
i = i + 1
|
||||||
|
return stack[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
create_node = create_node,
|
create_node = create_node,
|
||||||
|
merge_nodes = merge_nodes,
|
||||||
iter_children = iter_children,
|
iter_children = iter_children,
|
||||||
in_order_visitor = in_order_visitor,
|
in_order_visitor = in_order_visitor,
|
||||||
|
iter_in_order = iter_in_order,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
local ast = require("awesomewmdtl.ast")
|
||||||
local type Dag = require("awesomewmdtl.types.Dag")
|
local type Dag = require("awesomewmdtl.types.Dag")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
@ -10,26 +11,98 @@ local function new(): Dag
|
||||||
return dag
|
return dag
|
||||||
end
|
end
|
||||||
|
|
||||||
local function push_module(dag: Dag, module_path: string, root_node: Node)
|
local function push_module(dag: Dag, module_path: string, node: Node)
|
||||||
dag.modules[module_path] = root_node
|
local parent: Node = { children = dag.modules }
|
||||||
|
local current_path = ""
|
||||||
|
for breadcrumb in module_path:gmatch("([^%.]+)") do
|
||||||
|
current_path = current_path == "" and breadcrumb or current_path .. "." .. breadcrumb
|
||||||
|
|
||||||
|
if current_path == node.module_path then
|
||||||
|
local found = utils.find(parent.children, function(n: Node): boolean
|
||||||
|
return n.module_path == node.module_path
|
||||||
|
end)
|
||||||
|
if found then
|
||||||
|
ast.merge_nodes(found, node)
|
||||||
|
else
|
||||||
|
table.insert(parent.children, node)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local current: Node = nil
|
||||||
|
for _, n in ipairs(parent.children) do
|
||||||
|
if n.module_path == current_path then
|
||||||
|
current = n
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if current == nil then
|
||||||
|
current = {
|
||||||
|
children = {},
|
||||||
|
name = utils.capitalize(breadcrumb),
|
||||||
|
module_path = current_path,
|
||||||
|
dependencies = {},
|
||||||
|
token = "module",
|
||||||
|
}
|
||||||
|
push_module(dag, current_path, current)
|
||||||
|
end
|
||||||
|
|
||||||
|
parent = current
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function push_global_nodes(dag: Dag, nodes: { Node })
|
local function push_global_nodes(dag: Dag, nodes: { Node })
|
||||||
utils.spread(dag.global_nodes, nodes)
|
utils.spread(dag.global_nodes, nodes)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function iter_modules(dag: Dag): (function(): string, Node)
|
local function iter_modules(dag: Dag): (function(): Node)
|
||||||
return pairs(dag.modules)
|
local stack: { Node } = {}
|
||||||
|
for _, root in ipairs(dag.modules) do
|
||||||
|
for node in ast.iter_in_order(root) do
|
||||||
|
if node.token == "module" then
|
||||||
|
table.insert(stack, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
return function(): Node
|
||||||
|
i = i + 1
|
||||||
|
return stack[i]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function iter_global_nodes(dag: Dag): (function(): integer, Node)
|
local function iter_global_nodes(dag: Dag): (function(): integer, Node)
|
||||||
return pairs(dag.global_nodes)
|
return pairs(dag.global_nodes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function find_module(dag: Dag, module_path: string): Node
|
||||||
|
local current_path = ""
|
||||||
|
for breadcrumb in module_path:gmatch("([^%.]+)") do
|
||||||
|
current_path = current_path == "" and breadcrumb or current_path .. "." .. breadcrumb
|
||||||
|
local current: Node = nil
|
||||||
|
|
||||||
|
if current_path == module_path then
|
||||||
|
return current
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, n in ipairs(dag.modules) do
|
||||||
|
if n.module_path == current_path then
|
||||||
|
current = n
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if current == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
new = new,
|
new = new,
|
||||||
push_module = push_module,
|
push_module = push_module,
|
||||||
push_global_nodes = push_global_nodes,
|
push_global_nodes = push_global_nodes,
|
||||||
iter_modules = iter_modules,
|
iter_modules = iter_modules,
|
||||||
iter_global_nodes = iter_global_nodes,
|
iter_global_nodes = iter_global_nodes,
|
||||||
|
find_module = find_module,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,12 @@ local filesystem <const> = require("awesomewmdtl.filesystem")
|
||||||
local printer <const> = require("awesomewmdtl.printer")
|
local printer <const> = require("awesomewmdtl.printer")
|
||||||
local List <const> = require("pl.List")
|
local List <const> = require("pl.List")
|
||||||
local logger <const> = require("awesomewmdtl.logger")
|
local logger <const> = require("awesomewmdtl.logger")
|
||||||
local Map <const> = require("pl.Map")
|
|
||||||
local Module_Info <const> = require("awesomewmdtl.entity.Module_Info")
|
local Module_Info <const> = require("awesomewmdtl.entity.Module_Info")
|
||||||
local module_dependencies <const> = require("awesomewmdtl.visitors.module_dependencies")
|
local module_dependencies <const> = require("awesomewmdtl.visitors.module_dependencies")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
local node_fixer <const> = require("awesomewmdtl.visitors.node_fixer")
|
local node_fixer <const> = require("awesomewmdtl.visitors.node_fixer")
|
||||||
local property <const> = require("awesomewmdtl.property")
|
local property <const> = require("awesomewmdtl.property")
|
||||||
local scraper <const> = require("awesomewmdtl.scraper")
|
local scraper <const> = require("awesomewmdtl.scraper")
|
||||||
local stringx <const> = require("pl.stringx")
|
|
||||||
local type_mapping <const> = require("awesomewmdtl.visitors.type_mapping")
|
local type_mapping <const> = require("awesomewmdtl.visitors.type_mapping")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
|
@ -46,53 +44,6 @@ local function module_lists(
|
||||||
return all_module_infos, module_infos, global_module_infos
|
return all_module_infos, module_infos, global_module_infos
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The module's children list produced can contain duplicates.
|
|
||||||
-- We ignore them for now because they are dismissed when building a Map for the printer.
|
|
||||||
local function modules_tree(modules: List<Module_Info.Module_Info>): Map<string, List<string>>
|
|
||||||
local tree: Map<string, List<string>> = Map()
|
|
||||||
for module in modules:iter() do
|
|
||||||
local parent = module.name:gmatch("(.*)%.(.*)$")()
|
|
||||||
if parent then
|
|
||||||
local ancestors = stringx.split(parent, ".")
|
|
||||||
for i = 1, #ancestors - 1 do
|
|
||||||
local ancestor = ancestors:slice(1, i):join(".")
|
|
||||||
if not tree:get(ancestor) then
|
|
||||||
tree:set(ancestor, List())
|
|
||||||
end
|
|
||||||
if not tree:get(ancestor):contains(parent) then
|
|
||||||
tree:get(ancestor):append(parent)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local parent_node = tree:get(parent)
|
|
||||||
if not parent_node then
|
|
||||||
tree:set(parent, List())
|
|
||||||
parent_node = tree:get(parent)
|
|
||||||
end
|
|
||||||
parent_node:append(module.name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return tree
|
|
||||||
end
|
|
||||||
|
|
||||||
--- TODO : rewrite this to use the DAG
|
|
||||||
local function do_module_init_definition(
|
|
||||||
module_infos: List<Module_Info.Module_Info>
|
|
||||||
)
|
|
||||||
local tree = modules_tree(module_infos)
|
|
||||||
for module, children in tree:iter() do
|
|
||||||
-- TODO : this map should be coupled with the all_module_infos list
|
|
||||||
local requires: Map<string, string> = Map()
|
|
||||||
for child in children:iter() do
|
|
||||||
local name = child:gmatch(".*%.(.*)$")()
|
|
||||||
requires:set(name, child)
|
|
||||||
end
|
|
||||||
filesystem.file_writer.write(
|
|
||||||
printer.module_init_definition.generate_teal(requires),
|
|
||||||
property.out_directory .. "/" .. stringx.split(module, "."):slice(1, -1):join("/") .. "/init.d.tl"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- TODO : rewrite the module_info thingy
|
--- TODO : rewrite the module_info thingy
|
||||||
local all_module_infos, module_infos, global_module_infos = module_lists(
|
local all_module_infos, module_infos, global_module_infos = module_lists(
|
||||||
property.base_url .. property.index_uri,
|
property.base_url .. property.index_uri,
|
||||||
|
@ -130,7 +81,7 @@ for module in module_infos:iter() do
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Run the visitors
|
-- Run the visitors
|
||||||
for _,root in dag.iter_modules(module_dag) do
|
for root in dag.iter_modules(module_dag) do
|
||||||
ast.in_order_visitor(root, function(node: Node)
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
node_fixer.visit(node, root)
|
node_fixer.visit(node, root)
|
||||||
end)
|
end)
|
||||||
|
@ -172,17 +123,17 @@ end
|
||||||
-- Write the DAG to a file
|
-- Write the DAG to a file
|
||||||
-- local inspect = require("inspect")
|
-- local inspect = require("inspect")
|
||||||
-- filesystem.file_writer.write(
|
-- filesystem.file_writer.write(
|
||||||
-- inspect(module_dag, { newline = "\n", indent = " ", depth = 2 }),
|
-- inspect(module_dag, { newline = "\n", indent = " " }),
|
||||||
-- "generated_dag.lua"
|
-- "generated_dag.lua"
|
||||||
-- )
|
-- )
|
||||||
|
|
||||||
log:info("Preprocessing finished")
|
log:info("Preprocessing finished")
|
||||||
|
|
||||||
-- Write modules types definitions to files
|
-- Write modules types definitions to files
|
||||||
for module_path, root in dag.iter_modules(module_dag) do
|
for root in dag.iter_modules(module_dag) do
|
||||||
filesystem.file_writer.write(
|
filesystem.file_writer.write(
|
||||||
printer.teal_type_definition.printer(root),
|
printer.teal_type_definition.printer(root),
|
||||||
property.out_directory .. "/" .. module_path:gsub("%.", "/") .. ".d.tl"
|
property.out_directory .. "/" .. root.module_path:gsub("%.", "/") .. ".d.tl"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -193,5 +144,4 @@ filesystem.file_writer.write(
|
||||||
property.out_directory .. "/global_env_def.d.tl"
|
property.out_directory .. "/global_env_def.d.tl"
|
||||||
)
|
)
|
||||||
|
|
||||||
do_module_init_definition(module_infos)
|
|
||||||
log:info("Module init files generated")
|
log:info("Module init files generated")
|
||||||
|
|
|
@ -6,6 +6,25 @@ local utils = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
local log = logger.log("scraper")
|
local log = logger.log("scraper")
|
||||||
|
|
||||||
|
local GEN_TEXT <const> = "-- This file was auto-generated.\n"
|
||||||
|
|
||||||
|
local function get_package_descendants(node: Node): { Node }
|
||||||
|
return utils.filter(
|
||||||
|
node.children,
|
||||||
|
function(child: Node): boolean
|
||||||
|
return child.token == "module"
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function nodes_to_string_map(nodes: { Node }): { string : string }
|
||||||
|
local map <const>: { string : string } = {}
|
||||||
|
for _, node in ipairs(nodes) do
|
||||||
|
map[node.name] = node.module_path
|
||||||
|
end
|
||||||
|
return map
|
||||||
|
end
|
||||||
|
|
||||||
local function render_types(types: { string }, separator: string, with_colon_prefix: boolean): string
|
local function render_types(types: { string }, separator: string, with_colon_prefix: boolean): string
|
||||||
if not types or #types == 0 then
|
if not types or #types == 0 then
|
||||||
return ""
|
return ""
|
||||||
|
@ -57,35 +76,62 @@ local function render_require(dependencies: { string : string }): string
|
||||||
return generated
|
return generated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function render_descendant(descendants: { Node }): string
|
||||||
|
local generated = ""
|
||||||
|
for _, descendant in ipairs(descendants) do
|
||||||
|
generated = generated .. string.format("%s: %s\n", utils.lowercase(descendant.name), descendant.name)
|
||||||
|
end
|
||||||
|
return generated
|
||||||
|
end
|
||||||
|
|
||||||
local record Node_Printer_Function
|
local record Node_Printer_Function
|
||||||
on_node: function(node: Node, indent_level: integer): string, integer
|
on_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
before_node: nil | function(node: Node, indent_level: integer): string, integer
|
-- optional functions
|
||||||
after_node: nil | function(node: Node, indent_level: integer): string, integer
|
before_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
after_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pre-declare functions to prevent forward reference errors
|
-- pre-declare functions to prevent forward reference errors
|
||||||
local print_teal: function(node: Node, indent_level: integer | nil): string
|
local print_teal: function(node: Node, indent_level: integer, parent_node: Node): string
|
||||||
local print_children: function(node: Node): string
|
local print_children: function(node: Node): string
|
||||||
|
|
||||||
local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
["module"] = {
|
["module"] = {
|
||||||
before_node = function(node: Node, indent_level: integer): string, integer
|
before_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
if "module" == parent_token then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
if node.global then
|
if node.global then
|
||||||
return render_code(
|
return render_code(
|
||||||
"-- This file was auto-generated.\n",
|
GEN_TEXT,
|
||||||
indent_level), indent_level
|
indent_level), indent_level
|
||||||
end
|
end
|
||||||
return render_code(
|
return render_code(
|
||||||
string.format(
|
string.format(
|
||||||
"-- This file was auto-generated.\n%s\nlocal record %s",
|
"%s%s\nlocal record %s",
|
||||||
render_require(node.dependencies), -- last require statement will have a newline
|
GEN_TEXT,
|
||||||
|
render_require(
|
||||||
|
utils.merge_map(
|
||||||
|
node.dependencies,
|
||||||
|
utils.pipe(
|
||||||
|
get_package_descendants,
|
||||||
|
nodes_to_string_map)(node) as { string : string } -- pipe needs to be promoted
|
||||||
|
)), -- last require statement will have a newline
|
||||||
node.name),
|
node.name),
|
||||||
indent_level), indent_level + 1
|
indent_level), indent_level + 1
|
||||||
end,
|
end,
|
||||||
on_node = function(node: Node, indent_level: integer): string, integer
|
on_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
if "module" == parent_token then
|
||||||
|
return render_code(
|
||||||
|
render_descendant({ node }),
|
||||||
|
indent_level), indent_level
|
||||||
|
end
|
||||||
return render_code(print_children(node), indent_level), indent_level
|
return render_code(print_children(node), indent_level), indent_level
|
||||||
end,
|
end,
|
||||||
after_node = function(node: Node, indent_level: integer): string, integer
|
after_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
if "module" == parent_token then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
if node.global then
|
if node.global then
|
||||||
return "", indent_level
|
return "", indent_level
|
||||||
end
|
end
|
||||||
|
@ -188,19 +234,22 @@ local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_teal(node: Node, indent_level: integer | nil): string
|
function print_teal(node: Node,
|
||||||
|
-- optional parameters
|
||||||
|
indent_level: integer, parent_node: Node): string
|
||||||
indent_level = indent_level or 0
|
indent_level = indent_level or 0
|
||||||
|
local parent_node_token = parent_node and parent_node.token
|
||||||
local printer = node_printer[node.token]
|
local printer = node_printer[node.token]
|
||||||
local generated = ""
|
local generated = ""
|
||||||
local full_generated = ""
|
local full_generated = ""
|
||||||
if printer.before_node then
|
if printer.before_node then
|
||||||
generated, indent_level = (printer.before_node as function(Node, integer): string, integer)(node, indent_level)
|
generated, indent_level = printer.before_node(node, indent_level, parent_node_token)
|
||||||
full_generated = generated
|
full_generated = generated
|
||||||
end
|
end
|
||||||
generated, indent_level = printer.on_node(node, indent_level)
|
generated, indent_level = printer.on_node(node, indent_level, parent_node_token)
|
||||||
full_generated = full_generated .. generated
|
full_generated = full_generated .. generated
|
||||||
if printer.after_node then
|
if printer.after_node then
|
||||||
generated, indent_level = (printer.after_node as function(Node, integer): string, integer)(node, indent_level)
|
generated, indent_level = printer.after_node(node, indent_level, parent_node_token)
|
||||||
full_generated = full_generated .. generated
|
full_generated = full_generated .. generated
|
||||||
end
|
end
|
||||||
return full_generated
|
return full_generated
|
||||||
|
@ -209,7 +258,7 @@ end
|
||||||
function print_children(node: Node): string
|
function print_children(node: Node): string
|
||||||
local generated = ""
|
local generated = ""
|
||||||
for _, child in ast.iter_children(node) do
|
for _, child in ast.iter_children(node) do
|
||||||
generated = generated .. print_teal(child)
|
generated = generated .. print_teal(child, 0, node)
|
||||||
end
|
end
|
||||||
return generated
|
return generated
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
|
||||||
local record Dag
|
local record Dag
|
||||||
modules: { string : Node } -- module_path (AKA "full name" `package.module.name`) -> root_node (token = "module")
|
modules: { Node } -- list of root modules
|
||||||
global_nodes: { Node }
|
global_nodes: { Node }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,16 @@ function utils.has_item(t: table, item: any): any
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function utils.find<T>(list: { T }, predicate: function(value: T, position: integer): boolean): T, integer
|
||||||
|
for position, value in ipairs(list) do
|
||||||
|
if predicate(value, position) then
|
||||||
|
return value, position
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function utils.filter<T>(list: { T }, predicate: function(value: T, position: integer): boolean): { T }
|
function utils.filter<T>(list: { T }, predicate: function(value: T, position: integer): boolean): { T }
|
||||||
local filtered: { T } = {}
|
local filtered: { T } = {}
|
||||||
|
|
||||||
|
@ -101,4 +111,27 @@ function utils.pairsByKeys<Key, Value>(list: { Key : Value }, comp: function(Key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- We expect the user to type at the call site
|
||||||
|
function utils.pipe(...: function): function(...: any): any...
|
||||||
|
local funcs = { ... }
|
||||||
|
return function(...: any): any...
|
||||||
|
local res = ...
|
||||||
|
for _, f in ipairs(funcs) do
|
||||||
|
res = f(res)
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.merge_map<T, U>(t1: { T : U }, t2: { T : U }): { T : U }
|
||||||
|
local merged: { T : U } = {}
|
||||||
|
for k, v in pairs(t1) do
|
||||||
|
merged[k] = v
|
||||||
|
end
|
||||||
|
for k, v in pairs(t2) do
|
||||||
|
merged[k] = v
|
||||||
|
end
|
||||||
|
return merged
|
||||||
|
end
|
||||||
|
|
||||||
return utils
|
return utils
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
local type Dag = require("awesomewmdtl.types.Dag")
|
local type Dag = require("awesomewmdtl.types.Dag")
|
||||||
|
local dag = require("awesomewmdtl.dag")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ function Module_Dependencies.visit(node: Node, mod: Node, d: Dag)
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
|
||||||
local dependency = d.modules[type_name] or d.modules[utils.lowercase(type_name)] or capi_class[type_name]
|
local dependency = dag.find_module(d, type_name) or dag.find_module(d, utils.lowercase(type_name)) or capi_class[type_name]
|
||||||
if dependency then
|
if dependency then
|
||||||
if dependency.name ~= mod.name then
|
if dependency.name ~= mod.name then
|
||||||
mod.dependencies[dependency.name] = dependency.module_path
|
mod.dependencies[dependency.name] = dependency.module_path
|
||||||
|
|
Loading…
Reference in New Issue