Skip to content

Commit

Permalink
Improve inline function for huge performance increases. New tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
DorianGray committed Oct 6, 2014
1 parent 1c2a9cb commit 2dfac4f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 38 deletions.
26 changes: 0 additions & 26 deletions lusty-0.4-0.rockspec

This file was deleted.

2 changes: 2 additions & 0 deletions spec/dummy/inlineFunction.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

return foo, bat
24 changes: 24 additions & 0 deletions spec/inline_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package.path = 'src/?.lua;'..package.path

describe('verify that inline handles environments properly', function()
local util = require 'util'

after_each(function()
util.clearCache()
end)

it('can set an environment', function()
local env = {foo='bar'}
assert('bar' == util.inline('spec.dummy.inlineFunction', env))
end)

it('can set an environment with multiple variables', function()
local env = {foo='bar', bat='baz'}
assert.same({'bar','baz'}, {util.inline('spec.dummy.inlineFunction', env)})
end)

it('can set an environment with no variables', function()
local env = {}
assert.equal(nil, util.inline('spec.dummy.inlineFunction', env))
end)
end)
52 changes: 40 additions & 12 deletions src/util.lua
Original file line number Diff line number Diff line change
@@ -1,25 +1,53 @@
local loader, loaded = package.loaders[2], package.loaded
local loaded = {}

local inlineMeta = {
__index = function(self, key)
return rawget(self, key) or _G[key]
local function loadModule(name)
local errors = {}
-- Find source
local modulePath = string.gsub(name, "%.", "/")
for path in string.gmatch(package.path, "([^;]+)") do
local fileName = string.gsub(path, "%?", modulePath)
local file = io.open(fileName, "rb")
if file then
return file:read("*a")
end
errors[#errors+1] = "\n\tno file '"..fileName.."' (attempted with lusty inline)"
end
}
return nil, table.concat(errors)
end

--load file, memoize, execute loaded function inside environment
local function inline(name, env)
local file = loaded[name]
if not file then
file = string.dump(loader(name))
local code, err = loadModule(name)
if not code then
error(err)
end
local keys ={}
for k in pairs(env) do
keys[#keys+1] = k
end

if #keys > 0 then
file, err = loadstring(
'local _env=select(1, ...)\nlocal '..table.concat(keys, ',')..
"=_env."..table.concat(keys, ",_env.")..
'\n'..code
)
else
file, err = loadstring(code)
end
if not file then error(err) end
loaded[name] = file
end
file = loadstring(file)
if type(file) == 'string' then
error(file)
end
return setfenv(file, setmetatable(env, inlineMeta))(name)
return file(env)
end

local function clearCache()
loaded = {}
end

return {
inline = inline
inline = inline,
clearCache = clearCache,
}

0 comments on commit 2dfac4f

Please sign in to comment.