|
|
|
@ -9,97 +9,149 @@ local function render_types(types: { string }): string
|
|
|
|
|
if not types or #types == 0 then
|
|
|
|
|
return ""
|
|
|
|
|
end
|
|
|
|
|
return ": " .. table.concat(types, " | ")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return ": " .. stringx.join(" | ", types)
|
|
|
|
|
local function dedent(str: string): string
|
|
|
|
|
return stringx.dedent(str):sub(1, -2)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function render_code(code: string, indent_level: integer): string
|
|
|
|
|
if not code or code == "" then
|
|
|
|
|
return ""
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local generated = ""
|
|
|
|
|
for line in stringx.lines(dedent(code)) do
|
|
|
|
|
generated = generated .. stringx.rstrip(string.rep(" ", 3 * indent_level) .. line) .. "\n"
|
|
|
|
|
end
|
|
|
|
|
return generated
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local record Node_Printer_Function
|
|
|
|
|
on_node: function(node: Node): string
|
|
|
|
|
before_node: nil | function(node: Node): string
|
|
|
|
|
after_node: nil | function(node: Node): string
|
|
|
|
|
on_node: function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
before_node: nil | function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
after_node: nil | function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- pre-declare functions to prevent forward reference errors
|
|
|
|
|
local print_teal: function(node: Node): string
|
|
|
|
|
local print_teal: function(node: Node, indent_level: integer | nil): string
|
|
|
|
|
local print_children: function(node: Node): string
|
|
|
|
|
|
|
|
|
|
local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
|
|
|
|
["module"] = {
|
|
|
|
|
before_node = function(node: Node): string
|
|
|
|
|
return "-- This file was auto-generated.\n\nlocal record " .. node.name .. "\n"
|
|
|
|
|
before_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(
|
|
|
|
|
string.format(
|
|
|
|
|
[[
|
|
|
|
|
-- This file was auto-generated.
|
|
|
|
|
|
|
|
|
|
local record %s
|
|
|
|
|
]],
|
|
|
|
|
node.name),
|
|
|
|
|
indent_level), indent_level + 1
|
|
|
|
|
end,
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
return print_children(node)
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(print_children(node), indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
after_node = function(node: Node): string
|
|
|
|
|
return "end\n\nreturn " .. node.name
|
|
|
|
|
after_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code("end", indent_level - 1) ..
|
|
|
|
|
"\n" ..
|
|
|
|
|
render_code(
|
|
|
|
|
string.format("return %s", node.name),
|
|
|
|
|
indent_level - 1
|
|
|
|
|
), indent_level - 1
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["record"] = {
|
|
|
|
|
before_node = function(node: Node): string
|
|
|
|
|
return "record " .. node.name .. "\n"
|
|
|
|
|
before_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(
|
|
|
|
|
string.format(
|
|
|
|
|
"record %s",
|
|
|
|
|
node.name),
|
|
|
|
|
indent_level), indent_level + 1
|
|
|
|
|
end,
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
return print_children(node)
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(print_children(node), indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
after_node = function(): string
|
|
|
|
|
return "end"
|
|
|
|
|
after_node = function(_: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code("end", indent_level - 1), indent_level - 1
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["enum"] = {
|
|
|
|
|
before_node = function(node: Node): string
|
|
|
|
|
return "enum " .. node.name .. "\n"
|
|
|
|
|
before_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(
|
|
|
|
|
string.format(
|
|
|
|
|
"enum %s",
|
|
|
|
|
node.name),
|
|
|
|
|
indent_level), indent_level + 1
|
|
|
|
|
end,
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
return print_children(node)
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(print_children(node), indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
after_node = function(): string
|
|
|
|
|
return "end"
|
|
|
|
|
after_node = function(_: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code("end", indent_level - 1), indent_level - 1
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["identifier"] = {
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
return "\"" .. node.name .. "\""
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(string.format('"%s"', node.name), indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["variable"] = {
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
return node.name .. render_types(node.types)
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
return render_code(
|
|
|
|
|
string.format(
|
|
|
|
|
"%s%s",
|
|
|
|
|
node.name,
|
|
|
|
|
render_types(node.types)),
|
|
|
|
|
indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["function"] = {
|
|
|
|
|
on_node = function(node: Node): string
|
|
|
|
|
on_node = function(node: Node, indent_level: integer): string, integer
|
|
|
|
|
local args = {}
|
|
|
|
|
for _, parameter in ipairs(node.parameters) do
|
|
|
|
|
table.insert(args, print_teal(parameter))
|
|
|
|
|
table.insert(args, print_teal(parameter):sub(1, -2)) -- need to remove the newline ending
|
|
|
|
|
end
|
|
|
|
|
return node.name .. ": function(" .. table.concat(args, ", ") .. ")" .. render_types(node.return_types)
|
|
|
|
|
return render_code(
|
|
|
|
|
string.format(
|
|
|
|
|
"%s: function(%s)%s",
|
|
|
|
|
node.name,
|
|
|
|
|
table.concat(args, ", "),
|
|
|
|
|
render_types(node.return_types)),
|
|
|
|
|
indent_level), indent_level
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
["metamethod"] = {
|
|
|
|
|
on_node = function(): string
|
|
|
|
|
on_node = function(): string, integer
|
|
|
|
|
log:warn("Metamethods are not supported yet")
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function print_teal(node: Node): string
|
|
|
|
|
function print_teal(node: Node, indent_level: integer | nil): string
|
|
|
|
|
indent_level = indent_level or 0
|
|
|
|
|
local printer = node_printer[node.token]
|
|
|
|
|
local generated = ""
|
|
|
|
|
local full_generated = ""
|
|
|
|
|
if printer.before_node then
|
|
|
|
|
generated = (printer.before_node as function(node: Node): string)(node)
|
|
|
|
|
generated, indent_level = (printer.before_node as function(Node, integer): string, integer)(node, indent_level)
|
|
|
|
|
full_generated = generated
|
|
|
|
|
end
|
|
|
|
|
generated = generated .. printer.on_node(node)
|
|
|
|
|
generated, indent_level = printer.on_node(node, indent_level)
|
|
|
|
|
full_generated = full_generated .. generated
|
|
|
|
|
if printer.after_node then
|
|
|
|
|
generated = generated .. (printer.after_node as function(node: Node): string)(node)
|
|
|
|
|
generated, indent_level = (printer.after_node as function(Node, integer): string, integer)(node, indent_level)
|
|
|
|
|
full_generated = full_generated .. generated
|
|
|
|
|
end
|
|
|
|
|
return generated
|
|
|
|
|
return full_generated
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function print_children(node: Node): string
|
|
|
|
|
local generated = ""
|
|
|
|
|
for _, child in ast.iter_children(node) do
|
|
|
|
|
generated = generated .. print_teal(child) .. "\n"
|
|
|
|
|
generated = generated .. print_teal(child)
|
|
|
|
|
end
|
|
|
|
|
return generated
|
|
|
|
|
end
|
|
|
|
|