Skip to content

Instantly share code, notes, and snippets.

@orbyfied
Last active September 4, 2022 12:30
Show Gist options
  • Save orbyfied/e2309c4d1180b7e8364191bbba544898 to your computer and use it in GitHub Desktop.
Save orbyfied/e2309c4d1180b7e8364191bbba544898 to your computer and use it in GitHub Desktop.
Simple library for aid in object oriented programming in Lua.
---@diagnostic disable: undefined-field
-- Check if the library has already been loaded
if _G.LIB_OBJECTS_LOADED then
return "already loaded"
end
------------------------------------------------
----- Utilities
------------------------------------------------
_G.tostringvalue = function(value)
if value == nil then
-- return nil
return "nil"
else
-- get and match type
local t = type(value)
if t == "string" then
return '"' .. value .. '"'
elseif t == "function" then
-- try and get function info with debug
if _G.debug and _G.debug.getinfo then
local data = debug.getinfo(value)
local fstr = "func: "
if data.name then
fstr = fstr .. data.name
end
print(table.tostring(data))
return fstr .. " (args: " .. data.nups .. ")"
else
return 'func'
end
else
-- use default tostring function
return tostring(value)
end
end
end
table.fromvarargs = function(...)
local t = { }
for i = 1, select("#", ...) do
t[i] = select(i, ...)
end
return t
end
table.isarray = function(table)
for k, _ in pairs(table) do
if type(k) ~= "number" then
return false
end
end
return true
end
table.tostring = function(data)
-- test if it is an array
local isarray = table.isarray(data)
-- start string
local str
if isarray then
str = "[ "
else
str = "{ "
end
-- build content
local i = 0
for k, v in pairs(data) do
-- add comma
if i ~= 0 then
str = str .. ", "
end
-- append key
str = str .. tostringvalue(k)
-- append =
str = str .. " = "
-- append value
str = str .. tostringvalue(v)
-- increment i
i = i + 1
end
-- finish string
if isarray then
str = str .. " ]"
else
str = str .. " }"
end
-- return
return str
end
------------------------------------------------
----- Objects
------------------------------------------------
-- Class List By Name
local classes = { }
-- Class Metatable
local ClassType = { }
ClassType.__index = ClassType
--- Creates a new instance without calling the constructor
--- @return table The instance with metatable set.
function ClassType:allocate_instance()
-- create empty
local instance = setmetatable({ }, self._prototype)
-- return
return instance
end
local function failwhencalled(self, ...)
error("Constructor has already been called.", 0)
end
--- Allocates a new instance and calls the constructor
--- @vararg any The arguments to call the constructor with.
--- @return table The instance.
function ClassType:new_instance(...)
-- allocate
local instance = self:allocate_instance()
-- call constructor
if instance["__init"] then
instance:__init(...)
-- dont allow constructor call
instance.__init = failwhencalled
end
-- return instance
return instance
end
--- Get the static instance.
--- @return table The static instance.
function ClassType:static()
-- return static instance
return self._static
end
-- Class Builder Function
local ClassBuilderType = { }
ClassBuilderType.__index = ClassBuilderType
function ClassBuilderType.__call(builder)
local class = build_class(builder)
return class._static
end
--- Create a new class builder with a given name.
--- @param name string The name of the class.
--- @return table The class builder.
local function class_builder(name)
local instance = setmetatable({}, ClassBuilderType)
instance["$name"] = name
return instance
end
--- Takes in a class builder with a name field
--- and builds a class object and prototype for
--- creating new instances.
--- @param builder table The class builder
--- @return table The lass object.
local function build_class(builder)
-- create class
local class = setmetatable({ }, ClassType)
-- set properties
class._name = builder["$name"]
-- build static prototype
local static_prototype = { }
static_prototype.__index = static_prototype
function static_prototype.__call(_, ...)
return class:new_instance(...)
end
-- build static instance
class._static = setmetatable({
["__class"] = class
}, static_prototype)
-- build prototype
class._prototype = builder
class._prototype.__index = class._prototype
class._prototype["__class"] = class
-- register class
classes[class._name] = class
-- return class
return class
end
--- @return table The class with the given name or nil.
local function get_class(name)
return classes[name]
end
--- @return table The class of the instance.
local function get_class_of(inst)
return inst["__class"]
end
-- Set Globals
_G.class_builder = class_builder
_G.build_class = build_class
_G.create_class = create_class
_G.get_class = get_class
_G.get_class_of = get_class_of
_G.classes = classes
-- Return Loaded
_G.LIB_OBJECTS_LOADED = true
return "loaded"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment