Created
February 18, 2010 23:54
-
-
Save leegao/308249 to your computer and use it in GitHub Desktop.
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 _mtg = getmetatable(_G) or {} | |
| function _mtg.__index(self, k) | |
| return rawget(self,k.."___macro") | |
| end | |
| setmetatable(_G,_mtg) | |
| function string.escape(text) | |
| local str = "" | |
| for i=1, #text do | |
| local chr = text:sub(i,i) | |
| local escape = "" | |
| if isIn(chr, {"(", ")"}) then escape = "%" end | |
| str = str .. escape..chr | |
| end | |
| return str | |
| end | |
| function isIn(obj, table) | |
| for _,v in ipairs(table) do | |
| if obj == v then return true end | |
| end | |
| end | |
| function get_locals(func) | |
| local n = 1 | |
| local locals = {} | |
| func = (type(func) == "number") and func + 1 or func | |
| while true do | |
| local lname, lvalue = debug.getlocal(func, n) | |
| if lname == nil then break end | |
| if lvalue == nil then lvalue = mynil end | |
| locals[lname] = lvalue | |
| n = n + 1 | |
| end | |
| return locals | |
| end | |
| Macro = setmetatable({}, {__call=function(self, ...) return self:init(...) end}) | |
| function Macro:init(...) | |
| --We want to retain processing capability even after declaration | |
| local args = {...} | |
| local __string = "" | |
| for _,obj in ipairs(args) do | |
| __string = __string .. tostring(obj) | |
| end | |
| local members = { | |
| __string = __string, | |
| type="Macro" | |
| } | |
| local methods = { | |
| __tostring__ = function(self, n) | |
| --Actual Processing Logic goes here | |
| local str = self.__string | |
| local match = "${.-[^\\]}" | |
| --Check if str has ${statement} | |
| local indices = {str:find(match)} | |
| while #indices > 0 do | |
| local sub = str:sub(indices[1]+2, indices[2]-1) | |
| local repl = str:sub(unpack(indices)) | |
| local final = "" | |
| local locals = get_locals(3+n) | |
| for k,_ in pairs(locals) do | |
| rawset(_G,k.."___macro",_) | |
| end | |
| --Evaluate | |
| local _fn, e = loadstring(sub) | |
| if not _fn then | |
| _fn, e = loadstring("return "..sub) | |
| end | |
| if not _fn then | |
| final = " "..e.." " | |
| else | |
| final = tostring(_fn() or " ") | |
| end | |
| for k,_ in pairs(locals) do | |
| rawset(_G,k.."___macro",nil) | |
| end | |
| str = str:gsub(repl:escape(), final) | |
| indices = {str:find(match)} | |
| end | |
| return str | |
| end, | |
| __tostring = function(self) | |
| return getmetatable(self).__tostring__(self, 2) | |
| end, | |
| __call = function(self) | |
| return getmetatable(self).__tostring__(self, 0) | |
| end | |
| } | |
| return setmetatable(members, methods) | |
| end | |
| test = Macro "Hello ${jack} ${'Bauer'}" | |
| function test1() | |
| local jack = "Jack" | |
| print(test) | |
| end | |
| test1() | |
| function test2() | |
| local jack = "No One" | |
| print(test) | |
| end | |
| test2() | |
| function test3() | |
| local test = Macro "Hello ${world}" | |
| local world = "World" | |
| print(test()) | |
| end | |
| test3() | |
| function test4() | |
| local test = Macro "Hello ${print('asdf'); return 'World'}" | |
| local world = "World" | |
| print(test) | |
| end | |
| test4() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment