Advertisement
LuaWeaver

wOOP 1.0

Feb 8th, 2013
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.19 KB | None | 0 0
  1. --DOCS FOUND AT http://pastebin.com/ym6aXhG1
  2.  
  3. local config=
  4. {
  5.         imply_self=true; --Remove the need for setting a self value in functions (removes the need for a colon)
  6.         self_name="self"; --What the name is for the self value
  7.        
  8.         using_userdata=true; --Use userdata to allow __gc and __len metamethods. NOTE - WITHOUT THIS, STRICT ERRORS, PRIVATE, AND READ ONLY VALUES WILL NOT FUNCTION.
  9.        
  10.         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
  11.        
  12.         private_values=true; --Use private values
  13.         private_value_index="__"; --How to start private values
  14.        
  15.         read_only_values=true; --Use read only values
  16.         read_only_value_index="_"; --How to start read only values
  17.        
  18.         class_config_location="__settings"; --Where the config is located.
  19.         class_config_setup= --How the config is setup.
  20.         {
  21.                 new="new";
  22.                 mt="mt";
  23.         };
  24. }
  25.  
  26. local classes={}
  27. local objects={}
  28.  
  29. local function locals(lev)
  30.         local variables = {}
  31.         local names={}
  32.         local idx = 1
  33.         while true do
  34.                 local ln, lv = debug.getlocal(lev, idx)
  35.                 if ln ~= nil then
  36.                         variables[idx] = lv
  37.                         names[idx]=ln
  38.                 else
  39.                         break
  40.                 end
  41.                 idx = 1 + idx
  42.         end
  43.         return variables,names
  44. end
  45.  
  46. function remove(usd)
  47.         local lev=2
  48.         repeat
  49.                 local valid=debug.getinfo(lev)
  50.                 if not valid then break end
  51.                 local list,names=locals(lev)
  52.                 local num=0
  53.                 for i,v in pairs(list) do
  54.                         if rawequal(v,usd) then
  55.                                 num=num+1
  56.                                 debug.setlocal(lev,i,nil)
  57.                         end
  58.                 end
  59.                 lev=lev+1
  60.         until false
  61.         usd=nil
  62.         collectgarbage()
  63. end
  64.  
  65. local function giveTabAProxy(tab,metatable) --Create a userdata representation of a table with a metatable
  66.         local proxy=newproxy(true)
  67.        
  68.         local mt=getmetatable(proxy)
  69.        
  70.         mt.__origtab=tab
  71.        
  72.         mt.__index=
  73.         function(usd,ind)
  74.                 if config["private_values"] then
  75.                         local start=config["private_value_index"]
  76.                         if ind:sub(1,#start)==start then
  77.                                 error("Attempt to index '"..ind.."' (a private value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't do that.
  78.                         end
  79.                 end
  80.                 if config["strict_errors"] then
  81.                         if not tab[ind]==nil then
  82.                                 error("Attempt to index '"..ind.."' (a nil value) of "..tostring(proxy)..", a wOOP object.") --Oops! You did something you're not supposed to.
  83.                         end
  84.                 end
  85.                 return tab[ind]
  86.         end
  87.        
  88.         mt.__newindex=
  89.         function(usd,ind,val)
  90.                 if config["read_only_values"] then
  91.                         local start=config["read_only_value_index"]
  92.                         if ind:sub(1,#start)==start then
  93.                                 error("Attempt to set '"..ind.."' (a read only value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't set read onlys (onlies?).
  94.                         end
  95.                 end
  96.                 if config["private_values"] then
  97.                         local start=config["private_value_index"]
  98.                         if ind:sub(1,#start)==start then
  99.                                 error("Attempt to set '"..ind.."' (a private value) of "..tostring(proxy)..", a wOOP object.") --Oops! Can't do that.
  100.                         end
  101.                 end
  102.                 if config["strict_errors"] then
  103.                         if not tab[ind]==nil then
  104.                                 error("Attempt to set '"..ind.."' (a nil value) of "..tostring(proxy)..", a wOOP object.") --Oops! You did something you're not supposed to.
  105.                         end
  106.                 end
  107.                 tab[ind]=val
  108.         end
  109.        
  110.         for method,val in pairs(metatable or {}) do
  111.                 if not mt[method] then
  112.                         mt[method]=val
  113.                 end
  114.         end
  115.        
  116.         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
  117.                 if not mt[method] then
  118.                         mt[method]=val
  119.                 end
  120.         end
  121.        
  122.         return proxy
  123. end
  124.  
  125. local function implySelfToFunctions(tab) --Change all functions to tables with __call metamethod set to do a little dance
  126.         for i,v in pairs(tab) do
  127.                 if type(v)=="function" then
  128.                         local func=v
  129.                         local tabWithMt={}
  130.                        
  131.                         setmetatable(tabWithMt,
  132.                         {
  133.                                 __call=
  134.                                 function(_,...)
  135.                                         if config["imply_self"] then
  136.                                                 _G.self=tab
  137.                                                 local args={func(...)}
  138.                                                 _G.self=nil
  139.                                                 return unpack(args)
  140.                                         else
  141.                                                 return func(...)
  142.                                         end
  143.                                 end
  144.                         })
  145.                        
  146.                         tab[i]=tabWithMt
  147.                 end
  148.         end
  149. end
  150.  
  151. local function newObj(name,...)
  152.         if not classes[name] then error("Class not found : "..name) end
  153.         local userdata=config["using_userdata"]
  154.         local implySelf=config["imply_self"]
  155.         local configLoc=config["class_config_location"]
  156.         local configTab=config["class_config_setup"]
  157.        
  158.         local settings=classes[name][configLoc]
  159.        
  160.         local new=settings['new']
  161.         local mt=settings[configTab['mt']]
  162.        
  163.         mt.__index=classes[name]
  164.         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
  165.                 if not mt[method] then
  166.                         mt[method]=val
  167.                 end
  168.         end
  169.        
  170.         table.remove(arg,1)
  171.        
  172.         local tab=new(unpack(arg))
  173.        
  174.         for i,v in pairs(classes[name]) do
  175.                 if not tab[i] then tab[i]=v end
  176.         end
  177.         if implySelf then
  178.                 implySelfToFunctions(tab)
  179.         end
  180.         local prox
  181.         if userdata then
  182.                 prox=giveTabAProxy(tab,mt)
  183.         else
  184.                 prox=setmetatable({},{__index=tab})
  185.         end
  186.         return prox
  187. end
  188.        
  189. local function realClass(tab,name,extends) --Do a short jig to remove the parentheses
  190.         local mt={}
  191.         local index={}
  192.         if extends and classes[extends] then
  193.                 index=classes[extends]
  194.         elseif classes.base then
  195.                 index=classes.base
  196.         end
  197.         for i,v in pairs(index) do
  198.                 if not tab[i] then tab[i]=v end
  199.         end
  200.        
  201.         local configLoc=config["class_config_location"]
  202.         if not tab[configLoc] then
  203.                 tab[configLoc]={}
  204.         end
  205.         setmetatable(tab[configLoc],{__index=index[configLoc] or {}})
  206.        
  207.         mt.__tostring=function() return "wOOP Class "..name end
  208.         mt.__metatable=false
  209.         mt.__concat=function(a,b) return tostring(a)..tostring(b) end
  210.         mt.__call=function(...) return newObj(name,...) end
  211.         tab.className=name
  212.         tab.extends=extends or "base"
  213.        
  214.         setmetatable(tab,mt)
  215.         classes[name]=tab
  216.         _G[name]=tab
  217. end
  218.  
  219. local function class3(tab,name)
  220.         return function(arg)
  221.                 realClass(arg,name,tab)
  222.         end
  223. end
  224.  
  225. local function class2(name)
  226.         return function(arg)
  227.                 if type(arg)=="table" then
  228.                         realClass(arg,name)
  229.                 else
  230.                         return class3(arg,name)
  231.                 end
  232.         end
  233. end
  234.  
  235. function class(name)
  236.         return class2(name)
  237. end
  238.  
  239. class "base"
  240. {
  241.         isA=
  242.         function(name)
  243.                 if self.className==name then
  244.                         return true
  245.                 end
  246.                 local var=self.extends
  247.                 while var~=name do
  248.                         var=classes[var].extends
  249.                         if var=="base" or not var then
  250.                                 return false
  251.                         end
  252.                 end
  253.                 return var
  254.         end,
  255.        
  256.         __settings=
  257.         {
  258.                 new=function(...) return {} end,
  259.                 mt={__gc=function(self) print(self.className) end}
  260.         }
  261. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement