To implement a domain specific language, within lua,
I want to add barewords to the language.
So that
print("foo")
could be written as print(foo)
The way I have done this is by changing the metatable of the enviroment table _G
.
mt = {__index = function(tbl,key) return key end}
setmetatable(_G, mt)
And that works, because retrieving the value of variable foo
is done by _G.foo
which is equivalent to _G["foo"]
Is this a good approach?
Are there hidden downsides?
Is there a better way?
Can I do it so that barewords only work inside a certain file?
(Perhaps by executing that file, from another luascript, using loadstring
)
As soon as someone declares a local with the same name of your "keywords" it will shadow your "keyword/global var" and your mechanism will fail:
and note that you cannot prevent the definition of local variables in a script.
Edit: (answering to a comment).
Are you using a customized Lua engine? You cannot prevent entering local scope, because you are always in local scope. It is exactly the other way around: technically there is no global scope in Lua (with the same meaning as in C, for example). There is a global namespace (implemented as a table), instead. The mechanisms for accessing globals differs between Lua 5.1 (function environments) and Lua 5.2 (implicit
_ENV
prefixing), but the concept is almost the same.In particular, when a Lua script is loaded, whether by the interpreter, or by
load
,loadstring
,dofile
, etc., it is interpreted as the body of an anonymous function (a closure), usually referred to as the "main chunk". Thus there is always a local scope. In standard Lua you cannot prevent the definition of a local variable when the parser encounters alocal
statement in the script being loaded.