From 2dfac4f07fcb96de76b7d5b98e6c420352355155 Mon Sep 17 00:00:00 2001 From: Robert Ditthardt Date: Sun, 5 Oct 2014 20:53:39 -0700 Subject: [PATCH] Improve inline function for huge performance increases. New tests. --- lusty-0.4-0.rockspec | 26 ------------------ spec/dummy/inlineFunction.lua | 2 ++ spec/inline_spec.lua | 24 ++++++++++++++++ src/util.lua | 52 +++++++++++++++++++++++++++-------- 4 files changed, 66 insertions(+), 38 deletions(-) delete mode 100644 lusty-0.4-0.rockspec create mode 100644 spec/dummy/inlineFunction.lua create mode 100644 spec/inline_spec.lua diff --git a/lusty-0.4-0.rockspec b/lusty-0.4-0.rockspec deleted file mode 100644 index e4b16d6..0000000 --- a/lusty-0.4-0.rockspec +++ /dev/null @@ -1,26 +0,0 @@ -package = "lusty" -version = "0.4-0" -source = { - url = "https://github.com/Olivine-Labs/lusty/archive/v0.4.tar.gz", - dir = "lusty-0.4" -} -description = { - summary = "Lua web framework.", - detailed = [[ - An event-based web framework built for speed. - ]], - homepage = "http://olivinelabs.com/lusty/", - license = "MIT " -} -dependencies = { - "lua >= 5.1", - "busted >= 1.7-1", - "mediator_lua >= 1.1-2" -} -build = { - type = "builtin", - modules = { - ["lusty.init"] = "src/init.lua", - ["lusty.util"] = "src/util.lua" - } -} diff --git a/spec/dummy/inlineFunction.lua b/spec/dummy/inlineFunction.lua new file mode 100644 index 0000000..909f244 --- /dev/null +++ b/spec/dummy/inlineFunction.lua @@ -0,0 +1,2 @@ + +return foo, bat diff --git a/spec/inline_spec.lua b/spec/inline_spec.lua new file mode 100644 index 0000000..0795173 --- /dev/null +++ b/spec/inline_spec.lua @@ -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) diff --git a/src/util.lua b/src/util.lua index b1c69ed..1869083 100644 --- a/src/util.lua +++ b/src/util.lua @@ -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, }