jbe/bsw@0: #!/usr/bin/env lua jbe/bsw@0: jbe/bsw@0: local error = error jbe/bsw@0: local getmetatable = getmetatable jbe/bsw@0: local rawset = rawset jbe/bsw@0: local setmetatable = setmetatable jbe/bsw@0: jbe@64: local _M = {} jbe@64: if _ENV then jbe@64: _ENV = _M jbe@64: else jbe@64: _G[...] = _M jbe@64: setfenv(1, _M) jbe@64: end jbe/bsw@0: jbe/bsw@0: metatable = { jbe/bsw@0: __tostring = function(self) jbe/bsw@0: return "nil" .. self[1] jbe/bsw@0: end, jbe/bsw@0: __newindex = function() jbe/bsw@0: error("Objects representing nil are immutable.") jbe/bsw@0: end jbe/bsw@0: } jbe/bsw@0: jbe/bsw@0: nils = setmetatable({}, { jbe/bsw@0: __mode = "v", jbe/bsw@0: __index = function(self, level) jbe/bsw@0: if level > 0 then jbe/bsw@0: local result = setmetatable({ level }, metatable) jbe/bsw@0: rawset(self, level, result) jbe/bsw@0: return result jbe/bsw@0: end jbe/bsw@0: end, jbe/bsw@0: __newindex = function() jbe/bsw@0: error("Table is immutable.") jbe/bsw@0: end jbe/bsw@0: }) jbe/bsw@0: jbe/bsw@0: function lift(value) jbe/bsw@0: if value == nil then jbe/bsw@0: return nils[1] jbe/bsw@0: elseif getmetatable(value) == metatable then jbe/bsw@0: return nils[value[1]+1] jbe/bsw@0: else jbe/bsw@0: return value jbe/bsw@0: end jbe/bsw@0: end jbe/bsw@0: jbe/bsw@0: function lower(value) jbe/bsw@0: if value == nil then jbe/bsw@0: error("Cannot lower nil.") jbe/bsw@0: elseif getmetatable(value) == metatable then jbe/bsw@0: return nils[value[1]-1] jbe/bsw@0: else jbe/bsw@0: return value jbe/bsw@0: end jbe/bsw@0: end jbe@64: jbe@64: return _M