Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local config=
- {
- imply_self=true; --Remove the need for setting a self value in functions (removes the need for a colon)
- self_name="self"; --What the name is for the self value
- using_userdata=true; --Use userdata to allow __gc and __len metamethods.
- strict_errors=true; --Error if 1) Value inside an object does not exist or 2) Attempt to set a value of an object where the field does not exist
- private_values=true; --Use private values
- private_value_index="__"; --How to start private values
- read_only_values=true; --Use read only values
- read_only_value_index="_"; --How to start read only values
- class_config_location="__settings"; --Where the config is located. Set to "class" for directly in the class.
- class_config_setup= --How the config is setup.
- {
- new="new";
- mt="mt";
- };
- }
- if common_class then
- config.imply_self=false
- config.using_userdata=false
- config.class_config_location="class"
- config.class_config_setup.new="init"
- config.class_config_setup.mt=""
- elseif common_class==false then --don't do it, yo
- return
- end
- local classes={}
- local objects={}
- local function locals(lev)
- local variables = {}
- local names={}
- local idx = 1
- while true do
- local ln, lv = debug.getlocal(lev, idx)
- if ln ~= nil then
- variables[idx] = lv
- names[idx]=ln
- else
- break
- end
- idx = 1 + idx
- end
- return variables,names
- end
- function remove(usd)
- local lev=2
- repeat
- local valid=debug.getinfo(lev)
- if not valid then break end
- local list,names=locals(lev)
- local num=0
- for i,v in pairs(list) do
- if rawequal(v,usd) then
- num=num+1
- debug.setlocal(lev,i,nil)
- end
- end
- lev=lev+1
- until false
- usd=nil
- collectgarbage()
- end
- local function giveTabAProxy(tab,metatable,userdata) --Create a userdata representation of a table with a metatable
- if common_class then return tab end
- local proxy=userdata and newproxy(true) or setmetatable({},{})
- local mt=getmetatable(proxy)
- mt.__origtab=tab
- mt.__index=
- function(usd,ind)
- if config["private_values"] then
- local start=config["private_value_index"]
- if ind:sub(1,#start)==start then
- error("Attempt to index '"..ind.."' (a private value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't do that.
- end
- end
- if config["strict_errors"] then
- if not tab[ind]==nil then
- error("Attempt to index '"..ind.."' (a nil value) of "..tostring(proxy)..", a wOOP object.") --Oops! You did something you're not supposed to.
- end
- end
- return tab[ind]
- end
- mt.__newindex=
- function(usd,ind,val)
- if config["read_only_values"] then
- local start=config["read_only_value_index"]
- if ind:sub(1,#start)==start then
- error("Attempt to set '"..ind.."' (a read only value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't set read onlys (onlies?).
- end
- end
- if config["private_values"] then
- local start=config["private_value_index"]
- if ind:sub(1,#start)==start then
- error("Attempt to set '"..ind.."' (a private value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't do that.
- end
- end
- if config["strict_errors"] then
- if not tab[ind]==nil then
- error("Attempt to set '"..ind.."' (a nil value) of "..tostring(proxy)..", a wOOP object.") --Oops! You did something you're not supposed to.
- end
- end
- tab[ind]=val
- end
- for method,val in pairs(metatable or {}) do
- if not mt[method] then
- mt[method]=val
- end
- end
- for method,val in pairs({__tostring=function(a) return "wOOP object : "..a.className end,__concat=function(a,b) return tostring(a)..tostring(b) end}) do
- if not mt[method] then
- mt[method]=val
- end
- end
- return proxy
- end
- local function implySelfToFunctions(tab) --Change all functions to tables with __call metamethod set to do a little dance
- for i,v in pairs(tab) do
- if type(v)=="function" then
- local func=v
- local tabWithMt={}
- setmetatable(tabWithMt,
- {
- __call=
- function(_,...)
- if config["imply_self"] then
- local oldenv=getfenv(func)
- setfenv(func,setmetatable({[config.self_name]=tab},{__index=oldenv}))
- local args={func(...)}
- setfenv(func,oldenv)
- return unpack(args)
- else
- return func(...)
- end
- end
- })
- tab[i]=tabWithMt
- end
- end
- end
- local function inheritVals(to,from)
- for i,v in pairs(from) do
- if type(v)=="table" and to[i] then
- inheritVals(to[i],v)
- elseif to[i]==nil then
- to[i]=v
- end
- end
- end
- local function newObj(name,...)
- if not classes[name] then error("Class not found : "..name) end
- local userdata=config["using_userdata"]
- local implySelf=config["imply_self"]
- local configLoc=config["class_config_location"]
- local configTab=config["class_config_setup"]
- local settings=classes[name][configLoc]
- if configLoc=="class" then
- settings=classes[name]
- end
- local new=settings[configTab['new']]
- local mt=settings[configTab['mt']] or {}
- mt.__index=classes[name]
- for method,val in pairs({__tostring=function(a) return "wOOP object : "..a.className end,__concat=function(a,b) return tostring(a)..tostring(b) end}) do
- if not mt[method] then
- mt[method]=val
- end
- end
- local args={...}
- if not common_class then
- table.remove(args,1)
- end
- local tab=new(unpack(args))
- if not tab then tab={} end
- inheritVals(tab,classes[name])
- if implySelf then
- implySelfToFunctions(tab)
- end
- local prox
- prox=giveTabAProxy(tab,mt,userdata)
- if not common_class then
- setmetatable(tab,mt)
- end
- return prox
- end
- local function realClass(tab,name,extends) --Do a short jig to remove the parentheses
- local mt={}
- local index={}
- if extends and classes[extends] then
- index=classes[extends]
- elseif classes.base then
- index=classes.base
- end
- inheritVals(tab,index)
- for i,v in pairs(tab) do
- print(i,v)
- end
- local configLoc=config["class_config_location"]
- if not configLoc=="class" and not tab[configLoc] then
- tab[configLoc]={}
- end
- mt.__tostring=function() return "wOOP Class "..name end
- mt.__metatable=false
- mt.__concat=function(a,b) return tostring(a)..tostring(b) end
- mt.__call=function(...) return newObj(name,...) end
- tab.className=name
- if not common_class then
- tab.extends=extends or "base"
- else
- tab.super=extends
- end
- if not common_class then
- setmetatable(tab,mt)
- _G[name]=tab
- end
- classes[name]=tab
- end
- local function class3(tab,name)
- return function(arg)
- realClass(arg,name,tab)
- end
- end
- local function class2(name)
- return function(arg)
- if type(arg)=="table" then
- realClass(arg,name)
- else
- return class3(arg,name)
- end
- end
- end
- function class(name)
- return class2(name)
- end
- if config["imply_self"] then
- class "base"
- {
- isA=
- function(name)
- local _,self=next(getfenv(debug.getinfo(1).func))
- if self.className==name then
- return true
- end
- local var=self.extends
- while var~=name do
- var=classes[var].extends
- if var=="base" or not var then
- return false
- end
- end
- return var
- end,
- [config["class_config_location"]]=
- {
- [config.class_config_setup.new]=function(...) return {} end,
- [config.class_config_setup.mt]={}
- }
- }
- else
- class "base"
- {
- isA=
- function(self,name)
- if self.className==name then
- return true
- end
- local var=self.super
- while var~=name do
- var=classes[var].super
- if var=="base" or not var then
- return false
- end
- end
- return var
- end,
- [config["class_config_location"]]=
- {
- [config.class_config_setup.new]=function(...) return {} end,
- [config.class_config_setup.mt]={}
- }
- }
- end
- if config.class_config_location=="class" then
- classes.base[config.class_config_setup.new]=classes.base.class[config.class_config_setup.new]
- classes.base[config.class_config_setup.mt]=classes.base.class[config.class_config_setup.mt]
- classes.base.class=nil
- end
- if common_class then
- _G.common={}
- common.class=
- function(name,data,extends)
- realClass(data,name,extends and extends.className or "base")
- return classes[name]
- end
- common.instance=
- function(class,...)
- local args={...}
- return newObj(class.className,unpack(args))
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment