Lua 5.2 compatibility hack

Sat, 01 Nov 2014 23:34:21 +0000

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sat, 01 Nov 2014 23:34:21 +0000
changeset 5
7667b101cb1e
parent 4
4cb0d1dbc65b
child 6
219d7a7304f8

Lua 5.2 compatibility hack

compat_env.lua file | annotate | diff | comparison | revisions
config.lua file | annotate | diff | comparison | revisions
dependency.lua file | annotate | diff | comparison | revisions
err.lua file | annotate | diff | comparison | revisions
filecache.lua file | annotate | diff | comparison | revisions
handlers.lua file | annotate | diff | comparison | revisions
handlers/copy.lua file | annotate | diff | comparison | revisions
handlers/ignore.lua file | annotate | diff | comparison | revisions
handlers/render.lua file | annotate | diff | comparison | revisions
lgen.lua file | annotate | diff | comparison | revisions
log.lua file | annotate | diff | comparison | revisions
ltp/LICENSE file | annotate | diff | comparison | revisions
ltp/README file | annotate | diff | comparison | revisions
ltp/template.lua file | annotate | diff | comparison | revisions
ltp/util.lua file | annotate | diff | comparison | revisions
luaext.lua file | annotate | diff | comparison | revisions
markdown.lua file | annotate | diff | comparison | revisions
path.lua file | annotate | diff | comparison | revisions
plugin/breadcrumb.lua file | annotate | diff | comparison | revisions
plugin/inline.lua file | annotate | diff | comparison | revisions
scan.lua file | annotate | diff | comparison | revisions
test.lua file | annotate | diff | comparison | revisions
time.lua file | annotate | diff | comparison | revisions
tuple.lua file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compat_env.lua	Sat Nov 01 23:34:21 2014 +0000
@@ -0,0 +1,144 @@
+--[[
+  compat_env - see README for details.
+  (c) 2012 David Manura.  Licensed under Lua 5.1/5.2 terms (MIT license).
+--]]
+
+local M = {_TYPE='module', _NAME='compat_env', _VERSION='0.2.2.20120406'}
+
+local function check_chunk_type(s, mode)
+  local nmode = mode or 'bt' 
+  local is_binary = s and #s > 0 and s:byte(1) == 27
+  if is_binary and not nmode:match'b' then
+    return nil, ("attempt to load a binary chunk (mode is '%s')"):format(mode)
+  elseif not is_binary and not nmode:match't' then
+    return nil, ("attempt to load a text chunk (mode is '%s')"):format(mode)
+  end
+  return true
+end
+
+local IS_52_LOAD = pcall(load, '')
+if IS_52_LOAD then
+  M.load     = _G.load
+  M.loadfile = _G.loadfile
+else
+  -- 5.2 style `load` implemented in 5.1
+  function M.load(ld, source, mode, env)
+    local f
+    if type(ld) == 'string' then
+      local s = ld
+      local ok, err = check_chunk_type(s, mode)
+      if not ok then return ok, err end
+      local err; f, err = loadstring(s, source)
+      if not f then return f, err end
+    elseif type(ld) == 'function' then
+      local ld2 = ld
+      if (mode or 'bt') ~= 'bt' then
+        local first = ld()
+        local ok, err = check_chunk_type(first, mode)
+        if not ok then return ok, err end
+        ld2 = function()
+          if first then
+            local chunk=first; first=nil; return chunk
+          else return ld() end
+        end
+      end
+      local err; f, err = load(ld2, source); if not f then return f, err end
+    else
+      error(("bad argument #1 to 'load' (function expected, got %s)")
+            :format(type(ld)), 2)
+    end
+    if env then setfenv(f, env) end
+    return f
+  end
+
+  -- 5.2 style `loadfile` implemented in 5.1
+  function M.loadfile(filename, mode, env)
+    if (mode or 'bt') ~= 'bt' then
+      local ioerr
+      local fh, err = io.open(filename, 'rb'); if not fh then return fh,err end
+      local function ld()
+        local chunk; chunk,ioerr = fh:read(4096); return chunk
+      end
+      local f, err = M.load(ld, filename and '@'..filename, mode, env)
+      fh:close()
+      if not f then return f, err end
+      if ioerr then return nil, ioerr end
+      return f
+    else
+      local f, err = loadfile(filename); if not f then return f, err end
+      if env then setfenv(f, env) end
+      return f
+    end
+  end
+end
+
+if _G.setfenv then -- Lua 5.1
+  M.setfenv = _G.setfenv
+  M.getfenv = _G.getfenv
+else -- >= Lua 5.2
+  -- helper function for `getfenv`/`setfenv`
+  local function envlookup(f)
+    local name, val
+    local up = 0
+    local unknown
+    repeat
+      up=up+1; name, val = debug.getupvalue(f, up)
+      if name == '' then unknown = true end
+    until name == '_ENV' or name == nil
+    if name ~= '_ENV' then
+      up = nil
+      if unknown then
+        error("upvalues not readable in Lua 5.2 when debug info missing", 3)
+      end
+    end
+    return (name == '_ENV') and up, val, unknown
+  end
+
+  -- helper function for `getfenv`/`setfenv`
+  local function envhelper(f, name)
+    if type(f) == 'number' then
+      if f < 0 then
+        error(("bad argument #1 to '%s' (level must be non-negative)")
+              :format(name), 3)
+      elseif f < 1 then
+        error("thread environments unsupported in Lua 5.2", 3) --[*]
+      end
+      f = debug.getinfo(f+2, 'f').func
+    elseif type(f) ~= 'function' then
+      error(("bad argument #1 to '%s' (number expected, got %s)")
+            :format(type(name, f)), 2)
+    end
+    return f
+  end
+  -- [*] might simulate with table keyed by coroutine.running()
+  
+  -- 5.1 style `setfenv` implemented in 5.2
+  function M.setfenv(f, t)
+    local f = envhelper(f, 'setfenv')
+    local up, val, unknown = envlookup(f)
+    if up then
+      debug.upvaluejoin(f, up, function() return up end, 1) --unique upval[*]
+      debug.setupvalue(f, up, t)
+    else
+      local what = debug.getinfo(f, 'S').what
+      if what ~= 'Lua' and what ~= 'main' then -- not Lua func
+        error("'setfenv' cannot change environment of given object", 2)
+      end -- else ignore no _ENV upvalue (warning: incompatible with 5.1)
+    end
+    return f  -- invariant: original f ~= 0
+  end
+  -- [*] http://lua-users.org/lists/lua-l/2010-06/msg00313.html
+
+  -- 5.1 style `getfenv` implemented in 5.2
+  function M.getfenv(f)
+    if f == 0 or f == nil then return _G end -- simulated behavior
+    local f = envhelper(f, 'setfenv')
+    local up, val = envlookup(f)
+    if not up then return _G end -- simulated behavior [**]
+    return val
+  end
+  -- [**] possible reasons: no _ENV upvalue, C function
+end
+
+
+return M
--- a/lgen.lua	Mon Sep 14 00:16:13 2009 +0300
+++ b/lgen.lua	Sat Nov 01 23:34:21 2014 +0000
@@ -1,7 +1,12 @@
-
+     
 module('lgen', package.seeall)
 -- export src dst hierarchy
 
+-- Lua 5.1 setfenv/getfenv compatibility for Lua 5.2
+local CE = require('compat_env')
+_G.setfenv = CE.setfenv
+_G.getfenv = CE.getfenv
+
 require('scan')
 require('handlers')
 -- globally add missing stuff 

mercurial