[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: lexical metamethods
- From: David Manura <dm.lua@...>
- Date: Sat, 26 Jun 2010 17:42:15 -0400
As an experiment, I'd like to patch Lua with what I'd call "lexical
metamethods," where if a lexical function named after a metamethod is
defined, then all corresponding operations in the lexical scope go
through that function. For example,
$ cat test.lua
local function __index(...)
print("debug:",...)
return 2
end
print(_G.y.z)
-- expected output:
-- debug: table: _G y
-- debug: 2 z
-- 2
Here's an initial patch for the __index metamethod. It doesn't quite
work in general. Ideas solicited. (BTW, dearth of comments in the
source leads to needing to infer a lot of stuff from usage patterns.)
diff -ur ../o/lua-5.1.4//src/lparser.c ./src/lparser.c
--- ../o/lua-5.1.4//src/lparser.c 2007-12-28 10:32:23.000000000 -0500
+++ ./src/lparser.c 2010-06-26 17:29:16.710882800 -0400
@@ -408,9 +408,30 @@
/* field -> ['.' | ':'] NAME */
FuncState *fs = ls->fs;
expdesc key;
+
+ TString * indexname = G(ls->L)->tmname[TM_INDEX];
+ expdesc func;
+ if (singlevaraux(fs, indexname, &func, 1) != VGLOBAL) {
+ int base = fs->freereg;
+ luaK_exp2nextreg(fs, &func);
+ luaK_exp2nextreg(fs, v);
+
+ luaX_next(ls); /* skip the dot or colon */
+ checkname(ls, &key);
+ luaK_exp2nextreg(fs, &key);
+
+ luaK_codeABC(fs, OP_CALL, base, 1+2, 1+1);
+ init_exp(v, VNONRELOC, base);
+ fs->freereg = base+1;
+
+ return;
+ }
+
luaK_exp2anyreg(fs, v);
luaX_next(ls); /* skip the dot or colon */
checkname(ls, &key);
+
+
luaK_indexed(fs, v, &key);
}
================
$ ./src/lua test.lua
debug: table: 0x690728 y
./src/lua: test.lua:6: attempt to call a number value
stack traceback:
test.lua:6: in main chunk
[C]: ?
$ ./src/luac -p -l test.lua
main <test.lua:0,0> (12 instructions, 48 bytes at 0x6b90f0)
0+ params, 5 slots, 0 upvalues, 1 local, 4 constants, 1 function
1 [4] CLOSURE 0 0 ; 0x6b9260
2 [6] GETGLOBAL 1 -1 ; print
3 [6] MOVE 2 0
4 [6] GETGLOBAL 3 -2 ; _G
5 [6] LOADK 4 -3 ; "y"
6 [6] CALL 2 3 2
7 [6] MOVE 3 0 <------------ problem
8 [6] MOVE 3 2 <------------
9 [6] LOADK 4 -4 ; "z"
10 [6] CALL 3 3 2
11 [6] CALL 1 3 1
12 [6] RETURN 0 1
function <test.lua:1,4> (7 instructions, 28 bytes at 0x6b9260)
0+ params, 4 slots, 0 upvalues, 1 local, 3 constants, 0 functions
1 [2] GETGLOBAL 1 -1 ; print
2 [2] LOADK 2 -2 ; "debug:"
3 [2] VARARG 3 0
4 [2] CALL 1 0 1
5 [3] LOADK 1 -3 ; 2
6 [3] RETURN 1 2
7 [4] RETURN 0 1