4

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)

Frames Catherine White
  • 27,368
  • 21
  • 87
  • 137

1 Answers1

4

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:

print(foo)   -- does what you think
local foo = 2
print(foo)   -- argh!

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 a local statement in the script being loaded.

  • Actually i can prevent the definition of all variables. (I'm not sure why this works on local variables, i think it stops you ever entering local scope). At the metamethod: `__newindex = function (tbl,key,value) end` to `_G` My testing with lua 5.2, is that this stops many variable declaration from adding its key. (I feel dirty) – Frames Catherine White Sep 06 '13 at 12:37
  • I am using the Lua 5.2.1 from the standard debian repository. And I know, (but don't know why, as I said), but if I add the metamethod: `__newindex = function (tbl,key,value) end` to `_G`. Entering: `print(foo) local foo = 2 print(foo)` outputs: "foo foo" – Frames Catherine White Sep 07 '13 at 02:57
  • Weird. It shouldn't behave this way (and it does not for me - Windows XP, both Lua 5.1.5 and 5.2.2). Maybe a bug in 5.2.1 (but I'm very skeptical about it) or some non standard patch that was buggy. Try to update to 5.2.2 (or try it on another system) and see if you get the same behavior. BTW, are you really sure your Lua version was not patched in some way? Post a complete example that exhibit the behavior you are experimenting (http://www.sscce.org/). – LorenzoDonati4Ukraine-OnStrike Sep 07 '13 at 09:03