Created
May 12, 2022 01:08
-
-
Save tilkinsc/c2a64044adf8f23a030939b9e3272ca1 to your computer and use it in GitHub Desktop.
Function Environment go boom
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local class = {} | |
-- Derived from: http://lua-users.org/wiki/CopyTable | |
-- Copies a table | |
local shallowcopy = function(o) | |
local c = {} | |
if (type(o) ~= "table")then | |
c = o | |
return c | |
end | |
for i, v in pairs(o)do | |
c[i] = v | |
end | |
return c | |
end | |
-- Deletes class out of function env, calling if not specifying | |
local remove = function(lst, env) | |
if(not env)then | |
getfenv(2)[lst] = nil | |
return | |
end | |
env[lst] = nil | |
end | |
-- Deletes a class, calls its deconstructor using meta's Name for the class | |
local delete = function(data) | |
if(data["_"..data.meta.Name])then | |
data["_"..data.meta.Name]() | |
end | |
data = nil | |
end | |
-- Makes a class super to a base | |
local extend = function(base, super) | |
base.super = super | |
end | |
setmetatable(class, { | |
__call = function(self, str) | |
return function(tab) | |
assert(type(str) == "string", "Invalid parameters specified, expected 'string' got '" .. type(str) .."'") | |
assert(type(tab) == "table", "No or an incorrect body defined for class " .. str) | |
if(not tab.env)then | |
tab.env = getfenv(2) | |
end | |
tab.env["remove"] = remove | |
tab.env["delete"] = delete | |
tab.env["extend"] = extend | |
tab.env[str] = { | |
new = function(...) | |
local this = { | |
[str] = tab[str]; | |
public = shallowcopy(tab.public); | |
meta = {Name=str}; | |
} | |
local proxy = newproxy(true) | |
local private = shallowcopy(tab.private); | |
local list = {} | |
local deconst_name = "_"..str | |
local this_deconst = this[deconst_name] | |
local tab_deconst = tab[deconst_name] | |
local const_name = str | |
local this_const = this[const_name] | |
local indx_tab = {__index = getfenv(2)} | |
local list_meta = setmetatable(list, {__index = getfenv()}) | |
local index_meta = { | |
__index = function(a, b) | |
if(b == "meta")then | |
return this.meta | |
end | |
if(b == const_name)then | |
return this_const | |
end | |
if(b == deconst_name)then | |
return this_deconst | |
end | |
if(this.public[b])then | |
return list[b] | |
end | |
if(private.super)then | |
if(private.super[b])then | |
return private.super[b] | |
end | |
end | |
end; | |
__newindex = function(a, b, c) | |
this.public[b] = c | |
end; | |
} | |
local self_meta = { | |
__index = function(a,b) | |
if(b == "meta")then | |
return this.meta | |
end | |
return list[b] | |
end; | |
__newindex = function(a,b,c) | |
if(list[b])then | |
list[b] = c | |
return | |
end | |
error("Attempt to create a new variable in global space") | |
end; | |
} | |
-- Setup self indexing | |
list.self = newproxy(true) | |
for i, v in pairs(self_meta)do | |
getmetatable(list.self)[i] = v | |
end | |
-- Setup main proxy indexing | |
for i, v in pairs(index_meta)do | |
getmetatable(proxy)[i] = v | |
end | |
-- Add deconstructor | |
if(tab_deconst)then | |
this_deconst = tab_deconst | |
end | |
-- Feed references into the function space | |
for i, v in pairs(this.public)do | |
list[i] = v | |
end | |
for i, v in pairs(private)do | |
list[i] = v | |
end | |
-- For all functions, apply feed references to function space | |
for i, v in pairs(list)do | |
if(type(v) == "function")then | |
setfenv(v, setmetatable(list, indx_tab)) | |
end | |
end | |
-- Apply feed references to constructor, and if has, deconstructor function space | |
if(this_const)then | |
setfenv(this_const, list_meta) | |
end | |
if(this_deconst)then | |
setfenv(this_deconst, list_meta) | |
end | |
-- If has a super class, setup the super() constructor | |
if(tab.env[const_name].super)then | |
private.super = function(...) | |
private.super = tab.env[const_name].super.new(...) | |
end | |
end | |
-- Execute constructor, if have | |
if(this_const)then | |
this_const(...) | |
end | |
return proxy | |
end; | |
} | |
end | |
end; | |
}) | |
return class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment