Blog

Context aware Lua Macros

February 18th, 2010 0 Comments

Will automatically detect locals as well as global variables.

Usage: Macro “text ${Lua Code} more text”

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()

What happens inside a classroom.

February 17th, 2010 0 Comments

Haha, so I was in my math class, and I couldn’t help notice that everyone else around me were either asleep or not paying attention, which got me to think, what is the critical point for which students completely give up on the lectures and instead rebel.

Taking Chances (Kate Micucci)

February 3rd, 2010 0 Comments

This is a great cover of Taking Chances by the G4TV nominated #1 Female Comedian of 2009. Enjoy =D

I don’t like Haikus

February 3rd, 2010 0 Comments


I don't like Haikus
because they put restrictions
on my sentences.

Because seriously, how can you even write anything meaningful through this type of writing structure?

Recovery.Texas

February 2nd, 2010 0 Comments

This is an attempt at visualizing the amount of money distributed to Texas via the Recovery.gov program as of (last) November.

Recovery.Texas

Best Hello World App Ever :D

February 1st, 2010 0 Comments

Written in Python :D

See http://failboat.me/2009/cute-functions-creating-pseudo-operators-in-python/ for more details.

#Hello World

class Operator(object):
    def __init__(self, func, count=2):
        self._func_ = func
        self._args_ = []
        self._count_ = count
    def __ror__(self, first_arg):
        self._args_.append(first_arg)
        return self
    def __or__(self, arg):
        self._args_.append(arg)
        if len(self._args_) >= self._count_:
            return self(*self._args_)
        else:
            raise RuntimeError("Incorrect number of parameters")
    def __call__(self, *args, **kwargs):
        self._args_ = []
        return self._func_(*args, **kwargs)

def alpha(letter):
    @Operator
    def _alpha(a,b):
        return a+letter+b
    return _alpha

for c in range(65, 122):
    globals()[chr(c)] = alpha(chr(c))

print "H"|e|"l"|l|"o","W"|o|"r"|l|"d"

Lua Tutorials -> Luatut.com

February 1st, 2010 0 Comments

A new set of Lua Tutorials are coming out.

Lua Tutorial

http://luatut.com/

Lua Function Overloading

December 28th, 2009 0 Comments

This script will allow you to overload functions based on the type of the parameters passed in. For example, the following

function asdf()
	print("A")
end

function asdf_number(x)
	print(x)
end

function asdf_number_number(x, y)
	print(y)
end

asdf()
asdf(3)
asdf(3,4)
asdf(4,5,3)

Actual Source code:

function string.split(t, b)
	local cmd = {}
	local match = "[^%s]+"
	if b then
		match = "%w+"
	end
	if type(b) == "string" then match = "[^"..b.."]+" end
	for word in string.gmatch(t, match) do
		table.insert(cmd, word)
	end
	return cmd
end

local __types = {number=1, string=2, table=3, boolean=4, ["function"]=5, ["nil"]=6}

local _mt = getmetatable(_G) or {}
_mt.__newindex = function(self, key, val)
	if type(val) ~= "function" then
		return rawset(self, key, val)
	end

	if not self.__registry then self.__registry = {} end

	local keys = key:split("_")
	local fn = keys[1]
	local types = keys
	table.remove(types, 1)
	for _i, type in ipairs(types) do
		if not type then
			self.__registry[fn] = {[0]=val}
			return rawset(self, key, val)
		end
		if not __types[type] then
			return rawset(self, key, val)
		end
	end

	local o_fn = rawget(self, fn) or function(...) return arg end
	local n_fn = function(...)
		local args = {...}
		for i, _type in ipairs(types) do
			if type(args[i]) ~= _type then
				return o_fn(...)
			end
		end
		return val(...)
	end
	return rawset(self, fn, n_fn)
end
_G=setmetatable(_G, _mt)