lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Jan 06, 2003 at 10:25 -0000, xenarcher <nickl@volition-inc.com> wrote:
> Consider the following Lua code:
> 
>    SomeVariable = 1
> 
>    function ClearSomeVariable()
>       SomeVariabl = 0  -- NOTE THE TYPO!
>    end
> 
> If the user accidentally writes the above code, typo and all, I want 
> to be able to catch this as a bug. However, the default 
> implementation of Lua allows global variables to be defined anywhere. 
> As such, the above code is quite valid and simply creates a second 
> global variable, "SomeVariabl", alongside the original 
> global, "SomeVariable".
> 
> My question is: is there an easy way to modify the Lua source to only 
> allow global variable definitions at the top level? (i.e.: outside 
> all code blocks, like C/C++) How would one go about doing this? There 
> must be some way to determine in the parser how many levels deep you 
> are. Even a simple assert to disallow the above code would be fine 
> for my purposes.

Here's some quickie draconian code that might fit your needs.
Basically it makes an error if you try to assign to a global whose
current value is nil (i.e. undefined).  It doesn't catch typos until
run-time, but then it works with stock Lua 4.0.


---- guard_globals.lua ---

function catch_assignment_to_undefined_global(varname, newvalue)
	assert(rawget(globals(), varname) == nil)
	error("assignment to undefined global \"" .. varname .. "\"; use global(\"var\", val) to define global variables")
end

-- special function to define a global var.
function global(varname, newvalue)
	rawset(globals(), varname, newvalue)
end

function expose_globals()
	settagmethod(tag(nil), "setglobal", nil)	-- restore default behavior
end

function guard_globals()
	settagmethod(tag(nil), "setglobal", catch_assignment_to_undefined_global)
end


-- example usage

SomeVariable = 1

function ClearSomeVariable()
	SomeVariabl = 0		-- here's the typo
end

-- now see if we catch the typo
guard_globals()

ClearSomeVariable()

-- once guard_globals() is up, you can use global() to define a single new global,
-- or expose_globals() to turn off the guard.

---- end ----


-- 
Thatcher Ulrich
http://tulrich.com