Skip to content

Instantly share code, notes, and snippets.

@SquidDev
Last active January 2, 2020 11:02
Show Gist options
  • Save SquidDev/601141fd27aede483c5ece31c2869a9b to your computer and use it in GitHub Desktop.
Save SquidDev/601141fd27aede483c5ece31c2869a9b to your computer and use it in GitHub Desktop.
Generate Amulet binding
--[[
ᐅ cat another.lua
return { a = 1, b = function() end }
ᐅ lua5.3 dump.lua another
external val another_b : unit -> 'a = "require(\"another\").b"
external val another_a : float = "require(\"another\").a"
(* external val another : table = "require(\"another\")" *)
]]
local module = ... or error("gen-aml.lua MODULE")
local function print_binding(name, path, val)
local ty = type(val)
local aml_ty
if ty == "number" then
aml_ty = "float"
elseif ty == "boolean" then
aml_ty = "bool"
elseif ty == "table" then
for k, v in pairs(val) do
if type(k) == "string" and k:match("^%a[%w_]*$") then
print_binding(name .. "_" .. k, path .. "." .. k, v)
end
end
elseif ty == "function" then
local info = debug.getinfo(val, "Su")
if info and info.what == "Lua" then
if info.nparams == 0 then
aml_ty = "unit -> 'a"
else
aml_ty = ""
for i = 1, info.nparams do
aml_ty = aml_ty .. ("'%c -> "):format(96 + i)
end
aml_ty = aml_ty .. ("'%c"):format(96 + i)
end
end
end
if not aml_ty then io.write("(* ") end
io.write(("external val %s : %s = %q"):format(name, aml_ty or ty, path))
if not aml_ty then io.write(" *)") end
io.write("\n")
end
print_binding(module, ("require(%q)"):format(module), require(module))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment