lua-users home
lua-l archive

lexical metamethods

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


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

AltStyle によって変換されたページ (->オリジナル) /