[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: local variables and scope
- From: Makoto Hamanaka <naraxx800@...>
- Date: Sun, 28 Aug 2005 23:18:23 +0900
Hi,
I used Lua for some years and I'm currently in need of
explicit global declarations.
Roberto Ierusalimschy wrote:
> Follows a nice script to detect missing "local" declarations and other
> "wrong" uses of global variables.
>
> Simply put it in your path and add require"strict" to your program
> (or call "lua -lstrict").
Your code looks good, but I want to declare every global variables explicitly,
in all of my Lua code. Also, I want to allow nil values for globals.
So I made up an another alternative, including several part of your idea.
features
- explicit global declarations by,
global "myvar"
- global variables can be nil
(implicitly declared global variables are automatically registered as "declared")
- user can select implicit or explicit variable declaration on main chunk
(default behavior is : "allow implicit declaration on main chunk")
- explicit declarations can be "off" by calling use_implicit_globals()
- functions can implicitly declared only on main chunk
- if you want to run "explicitly" created lua codes without this module,
just define these functions to avoid any error.
function global() end
function use_explicit_globals() end
function use_implicit_globals() end
A declaration is implicit or explicit, depending on where the
declaration occurs. (extending Roberto's logic)
---------------------------- C | main chunk | other(in function)
-------------------------------------------------------------------------
normal Lua ----------------- implicit | implicit | implicit
use_explicit_globals() ----- implicit | implicit | explicit
use_explicit_globals(true) and
-----value is not function - implicit | explicit | explicit
---------value is function - implicit | implicit | explicit
some drawbacks:
- it may leads to bad condition if user change the global table manually by setfenv.
- an implicitly-declared-global-variables, which value is nil
when use_explicit_globals() is called, can't be registered.
Any feedback is welcome.
----------- example ------------
require "explicit_globals"
use_explicit_globals(true) -- use explicit declaration, even for main chunk
--- OK case
global "my_global_variable"
my_global_variable = 1
local a = my_global_variable
--- NG case
my_undeclared_variable = 1 -- NG
local a = my_undeclared_variable2 -- NG
--- functions declarations
function undeclared_global_func() end --- ok
undeclared_global_func2 = function() end --- ok
function test()
global "my_global_func"
function my_global_func() end --- ok
function undeclared_global_func3() end --- NG
end
test()
----------- explicit_globals.lua ------------
-- table for checking global var declaration
local gdef = {}
local gdef_enabled = nil
-- the function to define global vars
function global(n)
if not gdef_enabled then
error("calling function global() when explicit-globals not enabled",2)
end
if gdef[n] == true then
error("re-definition of global \"" .. tostring(n) .. "\"",2)
end
gdef[n] = true
return
end
local function registerglobal(t,n,v)
gdef[n] = true
rawset(t,n,v)
end
-- forbid implicit definition of global vars
function use_explicit_globals( is_explicit_in_main_chunk )
-- set metatable for gloval environment
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
-- include implicitly-declared globals in gdef table,
-- in case some of it becomes nil and __index,__newindex be called.
-- drawback: if the value is nil now, it will not be included.
for k,v in pairs(_G) do
gdef[k] = true
end
mt.__newindex = function (t,n,v)
if gdef[n] ~= nil then -- declared global
rawset(t,n,v);return
end
local w = debug.getinfo(2,"S").what
if w == "C" then -- in C chunk
registerglobal(t,n,v);return
end
if ( not is_explicit_in_main_chunk and w == "main" ) then -- in main chunk
registerglobal(t,n,v);return
end
if type(v) == "function" then
-- funtcion value
if w == "main" then
-- declatration of functions in main chunk is ok.
registerglobal(t,n,v);return
else
error("assignment of undeclared global function \"" .. tostring(n) .. "\" outside of main chunk. use global(\"var\", val)", 2)
end
else
-- not function value
error("assignment of undeclared global \"" .. tostring(n) .. "\". use global(\"var\", val)", 2)
end
end
mt.__index = function (t,n)
if gdef[n] == nil and debug.getinfo(2,"S").what ~= "C" then
error("attempt to use undeclared global \"" .. tostring(n) .. "\". use global(\"var\", val)", 2)
end
return rawget(t, n)
end
gdef_enabled = true
end
-- back to normal, implicit global declaration.
function use_implicit_globals()
local mt = getmetatable(_G)
if mt ~= nil then
mt.__newindex = nil
mt.__index = nil
end
gdef_enabled = nil
end
----------- explicit_globals.lua ------------
--
Makoto Hamanaka <naraxx800@yahoo.co.jp>