Initial commit. Note: this is broken right now.

This commit is contained in:
2026-01-12 13:47:14 +00:00
commit 7de1bb3ef0
6 changed files with 817 additions and 0 deletions

195
helper.lua Normal file
View File

@@ -0,0 +1,195 @@
local old_print = print
function print(...)
local info = debug.getinfo(2)
local line = info.currentline
local name = info.source
old_print(string.format("%i%s> ",line,name),...)
end
function log(...)
old_print(...)
end
-- HELPER FUNCTIONS
-- Insert every item in t1 into t0
function just(...)
local items = {...}
return function()
return table.unpack(items)
end
end
id = function(...) return ... end
function union(t0,t1)
for index,item in pairs(t0) do
t0[index] = t1
end
return t0
end
-- Iterate (ipairs without the index)
function iterate(...)
local iterator,tab,i = pairs(...)
return function(...)
local index,item = iterator(tab,i)
i = index
return item
end,tab,i
end
function indices(t)
if type(t) ~= "table" then
error(
string.format(
"Argument 1 '%s' must be a table",
tostring(t)
)
,2)
end
local indices = {}
for index,_ in pairs(t) do
table.insert(indices,index)
end
return indices
end
-- Ensures a table has a metatable
function ensure_metatable(t)
local meta = getmetatable(t)
if not meta then meta = {} setmetatable(t,meta) end
return meta
end
function strings(t,item)
ensure_metatable(t).__tostring = item
end
-- Makes a table callable
function calls(t,fun)
ensure_metatable(t).__call = fun
end
-- Makes a table record access
function indexes(t,fun)
ensure_metatable(t).__index = fun
end
-- Makes a table record setting
function modifies(t,fun)
ensure_metatable(t).__newindex = fun
end
-- Shallow table to string
function table_tostring(tab,sep)
local items = {}
for item in iterate(tab) do
table.insert(items,tostring(item))
end
return table.concat(items,sep)
end
function type_of(item)
local type_name = type(item)
if type_name == "table" then
local meta = getmetatable(item)
if not meta then
return "table"
else
return meta
end
else
return type_name
end
end
-- DEBUGGING FUNCTIONS
-- Runs a function
function assert_meta(...)
local metas = {...}
return function(x,raise)
local meta = getmetatable(x)
for tab in iterate(metas) do
if meta == tab then return end
end
local s_metas = {}
for meta in iterate(metas) do
table.insert(s_metas,tostring(meta))
end
local level = 2
local msg = string.format(
"Expected metatables '%s' but got '%s'",
table.concat(s_metas,","),
type(x)
)
if raise then
level = 3
msg = string.format(raise,msg)
end
error(msg,level)
end
end
function assert_type(...)
local types = {...}
return function(x,raise)
local t = type(x)
for name in iterate(types) do
if t == name then return end
end
local level = 2
local msg = string.format(
"Expected type '%s' but got '%s'",
table_tostring(types," or "),
type(x))
-- For argument errors
if raise then
level = 3
msg = string.format(raise,msg)
end
error(msg,level)
end
end
-- HELPER FUNCTIONS
function case_of(t)
return function(item,...)
return (t[item] or error(
string.format(
"Couldn't match '%s' in case.",
tostring(item)
),2
))(...)
end
end
-- Creates a (p)OOP class
function class(name)
local meta = {}
union(meta,{restrict = {}})
meta.__index = meta
strings(meta,just(name))
calls(meta,function(meta,...)
local new = {}
setmetatable(new,meta)
if meta.new then new:new(...) end
return new
end)
meta.__tostring = function(this)
if meta.string then return this:string() end
return name
end
return meta
end
-- Read a file's full contents
function read(path)
local file = io.open(path)
if not file then
error(
string.match("Could not open file '%s'.",path),3
)
end
local content = file:read("a")
return content
end
return _G