[ create a new paste ] login | about

Link: http://codepad.org/tLMkCXOq    [ raw code | output | fork ]

Lua, pasted on Apr 30:
local nt = {}

local function doEnvHack(start)
    start = start or 1
    if start < 1 then error() end
    for i=1+start,math.huge do
        if debug.getinfo(i) and debug.getinfo(i).what ~= "C" then
            if getfenv(i) ~= nt and debug.getmetatable(getfenv(i)) then
                return getfenv(i), i
            end
        end
        if not debug.getinfo(i) then
            return nt
        end
    end
    return nt
end

for x,y in pairs(_G) do
    nt[x]=y
end

setfenv(0,nt)

local function getStringMetatable(start)
    local env, nextstart = doEnvHack((start and start+1 or 1))
    while not debug.getmetatable(env).__stringmt do
        env, nextstart = doEnvHack(nextstart)
    end
    return debug.getmetatable(env).__stringmt
end

-- replace string metatable
debug.setmetatable(getfenv(0),{
    __stringmt = debug.getmetatable("")
})

local idx = 1

debug.setmetatable("",{

    -- Indexing
    __index = function(t,k)
        local smt_index = rawget(getStringMetatable(idx),"__index")
        if type(smt_index) == "function" then return smt_index(t,k)
        else return rawget(smt_index,k) end
    end,
    __newindex = function(t,k)
        local smt_newindex = rawget(getStringMetatable(idx),"__newindex")
        if type(smt_newindex) == "function" then smt_newindex(t,k,v)
        else rawset(smt_newindex,k,v) end
    end,
    
    -- Calling
    __call = function(t,...)
        return rawget(getStringMetatable(idx),"__call")(t,...)
    end,
    
    -- Math
    __add = function(o1,o2)
        return rawget(getStringMetatable(idx),"__add")(o1,o2)
    end,
    __sub = function(o1,o2)
        return rawget(getStringMetatable(idx),"__sub")(o1,o2)
    end,
    __mul = function(o1,o2)
        return rawget(getStringMetatable(idx),"__mul")(o1,o2)
    end,
    __div = function(o1,o2)
        return rawget(getStringMetatable(idx),"__div")(o1,o2)
    end,
    __mod = function(o1,o2)
        return rawget(getStringMetatable(idx),"__mod")(o1,o2)
    end,
    __pow = function(o1,o2)
        return rawget(getStringMetatable(idx),"__pow")(o1,o2)
    end,
    __unm = function(o1,o2)
        return rawget(getStringMetatable(idx),"__unm")(o1,o2)
    end,
    
    -- Etc
    __concat = function(o1,o2)
        return rawget(getStringMetatable(idx),"__concat")(o1,o2)
    end,
    __len = function(t)
        return rawget(getStringMetatable(idx),"__len")(t)
    end,
    
    -- Compare
    __eq = function(o1,o2)
        return rawget(getStringMetatable(idx),"__eq")(o1,o2)
    end,
    __lt = function(o1,o2)
        return rawget(getStringMetatable(idx),"__lt")(o1,o2)
    end,
    __le = function(o1,o2)
        return rawget(getStringMetatable(idx),"__le")(o1,o2)
    end
});

function f()
    print(("this is a test"):lower())
end


local fenv = {}
for x,y in pairs(_G) do fenv[x]=y end

f() -- call it, no string metatable
setfenv(f,setmetatable(fenv,{__stringmt = {__index = {lower = string.upper}}}))
f() -- call it, with string metatable where __index.lower = string.upper


Output:
1
2
this is a test
THIS IS A TEST


Create a new paste based on this one


Comments: