aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-05 10:00:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-05 10:00:17 -0300
commit046a3d6173792b7d4d4d26a4e063e2fe383c10a7 (patch)
treeefe5a4544585084ab6e8d301847cc8568a1cc955
parent001f2bdd0e2f8803889c1b5164b57a51e44aef5b (diff)
downloadlua-046a3d6173792b7d4d4d26a4e063e2fe383c10a7.tar.gz
lua-046a3d6173792b7d4d4d26a4e063e2fe383c10a7.tar.bz2
lua-046a3d6173792b7d4d4d26a4e063e2fe383c10a7.zip
tag methods are always functions, so don't need to store a whole object
-rw-r--r--ldebug.c16
-rw-r--r--ldo.c15
-rw-r--r--ldo.h4
-rw-r--r--lgc.c39
-rw-r--r--lstate.c8
-rw-r--r--lstate.h7
-rw-r--r--ltests.c12
-rw-r--r--ltm.c63
-rw-r--r--ltm.h52
-rw-r--r--lvm.c77
10 files changed, 161 insertions, 132 deletions
diff --git a/ldebug.c b/ldebug.c
index 8a9a2ca6..f3b92af9 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 1.43 2000/10/02 20:10:55 roberto Exp roberto $ 2** $Id: ldebug.c,v 1.44 2000/10/05 12:14:08 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -203,12 +203,14 @@ static void lua_funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
203 203
204 204
205static const char *travtagmethods (lua_State *L, const TObject *o) { 205static const char *travtagmethods (lua_State *L, const TObject *o) {
206 int e; 206 if (ttype(o) == LUA_TFUNCTION) {
207 for (e=0; e<IM_N; e++) { 207 int e;
208 int t; 208 for (e=0; e<TM_N; e++) {
209 for (t=0; t<=L->last_tag; t++) 209 int t;
210 if (luaO_equalObj(o, luaT_getim(L, t,e))) 210 for (t=0; t<=L->last_tag; t++)
211 return luaT_eventname[e]; 211 if (clvalue(o) == luaT_gettm(L, t, e))
212 return luaT_eventname[e];
213 }
212 } 214 }
213 return NULL; 215 return NULL;
214} 216}
diff --git a/ldo.c b/ldo.c
index 281ef22e..11d6c5a6 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.101 2000/10/04 12:16:08 roberto Exp roberto $ 2** $Id: ldo.c,v 1.102 2000/10/05 12:14:08 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -142,10 +142,11 @@ static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) {
142} 142}
143 143
144 144
145void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { 145void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults) {
146 StkId base = L->top - nParams; 146 StkId base = L->top - nParams;
147 luaD_openstack(L, base); 147 luaD_openstack(L, base);
148 *base = *f; 148 clvalue(base) = f;
149 ttype(base) = LUA_TFUNCTION;
149 luaD_call(L, base, nResults); 150 luaD_call(L, base, nResults);
150} 151}
151 152
@@ -163,12 +164,12 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
163 Closure *cl; 164 Closure *cl;
164 if (ttype(func) != LUA_TFUNCTION) { 165 if (ttype(func) != LUA_TFUNCTION) {
165 /* `func' is not a function; check the `function' tag method */ 166 /* `func' is not a function; check the `function' tag method */
166 const TObject *im = luaT_getimbyObj(L, func, IM_FUNCTION); 167 Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION);
167 if (ttype(im) == LUA_TNIL) 168 if (tm == NULL)
168 luaG_typeerror(L, func, "call"); 169 luaG_typeerror(L, func, "call");
169 luaD_openstack(L, func); 170 luaD_openstack(L, func);
170 *func = *im; /* tag method is the new function to be called */ 171 clvalue(func) = tm; /* tag method is the new function to be called */
171 LUA_ASSERT(ttype(func) == LUA_TFUNCTION, "invalid tag method"); 172 ttype(func) = LUA_TFUNCTION;
172 } 173 }
173 cl = clvalue(func); 174 cl = clvalue(func);
174 ci.func = cl; 175 ci.func = cl;
diff --git a/ldo.h b/ldo.h
index dab8fc6e..1058d34e 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 1.25 2000/09/25 16:22:42 roberto Exp roberto $ 2** $Id: ldo.h,v 1.26 2000/10/04 12:16:08 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -25,7 +25,7 @@ void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
25void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, 25void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook,
26 const char *event); 26 const char *event);
27void luaD_call (lua_State *L, StkId func, int nResults); 27void luaD_call (lua_State *L, StkId func, int nResults);
28void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); 28void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults);
29void luaD_checkstack (lua_State *L, int n); 29void luaD_checkstack (lua_State *L, int n);
30 30
31void luaD_breakrun (lua_State *L, int errcode); 31void luaD_breakrun (lua_State *L, int errcode);
diff --git a/lgc.c b/lgc.c
index 1aca4e20..02ca2794 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.69 2000/10/02 14:47:43 roberto Exp roberto $ 2** $Id: lgc.c,v 1.70 2000/10/05 12:14:08 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -63,16 +63,6 @@ static void marklock (lua_State *L, GCState *st) {
63} 63}
64 64
65 65
66static void marktagmethods (lua_State *L, GCState *st) {
67 int e;
68 for (e=0; e<IM_N; e++) {
69 int t;
70 for (t=0; t<=L->last_tag; t++)
71 markobject(st, luaT_getim(L, t,e));
72 }
73}
74
75
76static void markclosure (GCState *st, Closure *cl) { 66static void markclosure (GCState *st, Closure *cl) {
77 if (!ismarked(cl)) { 67 if (!ismarked(cl)) {
78 if (!cl->isC) 68 if (!cl->isC)
@@ -83,6 +73,18 @@ static void markclosure (GCState *st, Closure *cl) {
83} 73}
84 74
85 75
76static void marktagmethods (lua_State *L, GCState *st) {
77 int e;
78 for (e=0; e<TM_N; e++) {
79 int t;
80 for (t=0; t<=L->last_tag; t++) {
81 Closure *cl = luaT_gettm(L, t, e);
82 if (cl) markclosure(st, cl);
83 }
84 }
85}
86
87
86static void markobject (GCState *st, TObject *o) { 88static void markobject (GCState *st, TObject *o) {
87 switch (ttype(o)) { 89 switch (ttype(o)) {
88 case LUA_TUSERDATA: case LUA_TSTRING: 90 case LUA_TUSERDATA: case LUA_TSTRING:
@@ -269,8 +271,8 @@ static void collectudata (lua_State *L, int all) {
269 else { /* collect */ 271 else { /* collect */
270 int tag = next->u.d.tag; 272 int tag = next->u.d.tag;
271 *p = next->nexthash; 273 *p = next->nexthash;
272 next->nexthash = L->IMtable[tag].collected; /* chain udata */ 274 next->nexthash = L->TMtable[tag].collected; /* chain udata */
273 L->IMtable[tag].collected = next; 275 L->TMtable[tag].collected = next;
274 L->nblocks -= gcsizeudata; 276 L->nblocks -= gcsizeudata;
275 L->udt.nuse--; 277 L->udt.nuse--;
276 } 278 }
@@ -292,12 +294,13 @@ static void checkMbuffer (lua_State *L) {
292 294
293 295
294static void callgcTM (lua_State *L, const TObject *o) { 296static void callgcTM (lua_State *L, const TObject *o) {
295 const TObject *im = luaT_getimbyObj(L, o, IM_GC); 297 Closure *tm = luaT_gettmbyObj(L, o, TM_GC);
296 if (ttype(im) != LUA_TNIL) { 298 if (tm != NULL) {
297 int oldah = L->allowhooks; 299 int oldah = L->allowhooks;
298 L->allowhooks = 0; /* stop debug hooks during GC tag methods */ 300 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
299 luaD_checkstack(L, 2); 301 luaD_checkstack(L, 2);
300 *(L->top) = *im; 302 clvalue(L->top) = tm;
303 ttype(L->top) = LUA_TFUNCTION;
301 *(L->top+1) = *o; 304 *(L->top+1) = *o;
302 L->top += 2; 305 L->top += 2;
303 luaD_call(L, L->top-2, 0); 306 luaD_call(L, L->top-2, 0);
@@ -313,8 +316,8 @@ static void callgcTMudata (lua_State *L) {
313 L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */ 316 L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */
314 for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */ 317 for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */
315 TString *udata; 318 TString *udata;
316 while ((udata = L->IMtable[tag].collected) != NULL) { 319 while ((udata = L->TMtable[tag].collected) != NULL) {
317 L->IMtable[tag].collected = udata->nexthash; /* remove it from list */ 320 L->TMtable[tag].collected = udata->nexthash; /* remove it from list */
318 tsvalue(&o) = udata; 321 tsvalue(&o) = udata;
319 callgcTM(L, &o); 322 callgcTM(L, &o);
320 luaM_free(L, udata); 323 luaM_free(L, udata);
diff --git a/lstate.c b/lstate.c
index 874b35bd..e4e0bc33 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.41 2000/09/25 16:22:42 roberto Exp roberto $ 2** $Id: lstate.c,v 1.42 2000/09/29 12:42:13 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -73,7 +73,7 @@ lua_State *lua_open (int stacksize) {
73 L->rootproto = NULL; 73 L->rootproto = NULL;
74 L->rootcl = NULL; 74 L->rootcl = NULL;
75 L->roottable = NULL; 75 L->roottable = NULL;
76 L->IMtable = NULL; 76 L->TMtable = NULL;
77 L->last_tag = -1; 77 L->last_tag = -1;
78 L->refArray = NULL; 78 L->refArray = NULL;
79 L->refSize = 0; 79 L->refSize = 0;
@@ -103,8 +103,8 @@ void lua_close (lua_State *L) {
103 if (L->stack) 103 if (L->stack)
104 L->nblocks -= (L->stack_last - L->stack + 1)*sizeof(TObject); 104 L->nblocks -= (L->stack_last - L->stack + 1)*sizeof(TObject);
105 luaM_free(L, L->stack); 105 luaM_free(L, L->stack);
106 L->nblocks -= (L->last_tag+1)*sizeof(struct IM); 106 L->nblocks -= (L->last_tag+1)*sizeof(struct TM);
107 luaM_free(L, L->IMtable); 107 luaM_free(L, L->TMtable);
108 L->nblocks -= (L->refSize)*sizeof(struct Ref); 108 L->nblocks -= (L->refSize)*sizeof(struct Ref);
109 luaM_free(L, L->refArray); 109 luaM_free(L, L->refArray);
110 L->nblocks -= (L->Mbuffsize)*sizeof(char); 110 L->nblocks -= (L->Mbuffsize)*sizeof(char);
diff --git a/lstate.h b/lstate.h
index 9c31349a..2a93f663 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.39 2000/09/25 16:22:42 roberto Exp roberto $ 2** $Id: lstate.h,v 1.40 2000/09/29 12:42:13 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -32,6 +32,7 @@ struct Ref {
32 32
33 33
34struct lua_longjmp; /* defined in ldo.c */ 34struct lua_longjmp; /* defined in ldo.c */
35struct TM; /* defined in ltm.h */
35 36
36 37
37typedef struct stringtable { 38typedef struct stringtable {
@@ -59,8 +60,8 @@ struct lua_State {
59 stringtable strt; /* hash table for strings */ 60 stringtable strt; /* hash table for strings */
60 stringtable udt; /* hash table for udata */ 61 stringtable udt; /* hash table for udata */
61 Hash *gt; /* table for globals */ 62 Hash *gt; /* table for globals */
62 struct IM *IMtable; /* table for tag methods */ 63 struct TM *TMtable; /* table for tag methods */
63 int last_tag; /* last used tag in IMtable */ 64 int last_tag; /* last used tag in TMtable */
64 struct Ref *refArray; /* locked objects */ 65 struct Ref *refArray; /* locked objects */
65 int refSize; /* size of refArray */ 66 int refSize; /* size of refArray */
66 int refFree; /* list of free positions in refArray */ 67 int refFree; /* list of free positions in refArray */
diff --git a/ltests.c b/ltests.c
index 5ceebcb5..e7464e51 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.47 2000/10/02 20:10:55 roberto Exp roberto $ 2** $Id: ltests.c,v 1.48 2000/10/05 12:14:08 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -438,6 +438,16 @@ static int testC (lua_State *L) {
438 else if EQ("dostring") { 438 else if EQ("dostring") {
439 lua_dostring(L, luaL_check_string(L, getnum)); 439 lua_dostring(L, luaL_check_string(L, getnum));
440 } 440 }
441 else if EQ("settagmethod") {
442 int tag = getnum;
443 const char *event = getname;
444 lua_settagmethod(L, tag, event);
445 }
446 else if EQ("gettagmethod") {
447 int tag = getnum;
448 const char *event = getname;
449 lua_gettagmethod(L, tag, event);
450 }
441 else if EQ("type") { 451 else if EQ("type") {
442 lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); 452 lua_pushstring(L, lua_typename(L, lua_type(L, getnum)));
443 } 453 }
diff --git a/ltm.c b/ltm.c
index 1dfc8a72..1f0ac830 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 1.52 2000/10/03 14:27:44 roberto Exp roberto $ 2** $Id: ltm.c,v 1.53 2000/10/05 12:14:08 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -17,7 +17,7 @@
17#include "ltm.h" 17#include "ltm.h"
18 18
19 19
20const char *const luaT_eventname[] = { /* ORDER IM */ 20const char *const luaT_eventname[] = { /* ORDER TM */
21 "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub", 21 "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub",
22 "mul", "div", "pow", "unm", "lt", "concat", "gc", "function", 22 "mul", "div", "pow", "unm", "lt", "concat", "gc", "function",
23 "le", "gt", "ge", /* deprecated options!! */ 23 "le", "gt", "ge", /* deprecated options!! */
@@ -36,9 +36,9 @@ static int findevent (const char *name) {
36 36
37static int luaI_checkevent (lua_State *L, const char *name, int t) { 37static int luaI_checkevent (lua_State *L, const char *name, int t) {
38 int e = findevent(name); 38 int e = findevent(name);
39 if (e >= IM_N) 39 if (e >= TM_N)
40 luaO_verror(L, "event `%.50s' is deprecated", name); 40 luaO_verror(L, "event `%.50s' is deprecated", name);
41 if (e == IM_GC && t == LUA_TTABLE) 41 if (e == TM_GC && t == LUA_TTABLE)
42 luaO_verror(L, "event `gc' for tables is deprecated"); 42 luaO_verror(L, "event `gc' for tables is deprecated");
43 if (e < 0) 43 if (e < 0)
44 luaO_verror(L, "`%.50s' is not a valid event name", name); 44 luaO_verror(L, "`%.50s' is not a valid event name", name);
@@ -50,8 +50,8 @@ static int luaI_checkevent (lua_State *L, const char *name, int t) {
50/* events in LUA_TNIL are all allowed, since this is used as a 50/* events in LUA_TNIL are all allowed, since this is used as a
51* 'placeholder' for "default" fallbacks 51* 'placeholder' for "default" fallbacks
52*/ 52*/
53/* ORDER LUA_T, ORDER IM */ 53/* ORDER LUA_T, ORDER TM */
54static const char luaT_validevents[NUM_TAGS][IM_N] = { 54static const char luaT_validevents[NUM_TAGS][TM_N] = {
55 {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ 55 {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */
56 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ 56 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */
57 {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */ 57 {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */
@@ -67,16 +67,16 @@ int luaT_validevent (int t, int e) { /* ORDER LUA_T */
67 67
68static void init_entry (lua_State *L, int tag) { 68static void init_entry (lua_State *L, int tag) {
69 int i; 69 int i;
70 for (i=0; i<IM_N; i++) 70 for (i=0; i<TM_N; i++)
71 ttype(luaT_getim(L, tag, i)) = LUA_TNIL; 71 luaT_gettm(L, tag, i) = NULL;
72 L->IMtable[tag].collected = NULL; 72 L->TMtable[tag].collected = NULL;
73} 73}
74 74
75 75
76void luaT_init (lua_State *L) { 76void luaT_init (lua_State *L) {
77 int t; 77 int t;
78 luaM_growvector(L, L->IMtable, 0, NUM_TAGS, struct IM, "", MAX_INT); 78 luaM_growvector(L, L->TMtable, 0, NUM_TAGS, struct TM, "", MAX_INT);
79 L->nblocks += NUM_TAGS*sizeof(struct IM); 79 L->nblocks += NUM_TAGS*sizeof(struct TM);
80 L->last_tag = NUM_TAGS-1; 80 L->last_tag = NUM_TAGS-1;
81 for (t=0; t<=L->last_tag; t++) 81 for (t=0; t<=L->last_tag; t++)
82 init_entry(L, t); 82 init_entry(L, t);
@@ -84,9 +84,9 @@ void luaT_init (lua_State *L) {
84 84
85 85
86int lua_newtag (lua_State *L) { 86int lua_newtag (lua_State *L) {
87 luaM_growvector(L, L->IMtable, L->last_tag, 1, struct IM, 87 luaM_growvector(L, L->TMtable, L->last_tag, 1, struct TM,
88 "tag table overflow", MAX_INT); 88 "tag table overflow", MAX_INT);
89 L->nblocks += sizeof(struct IM); 89 L->nblocks += sizeof(struct TM);
90 L->last_tag++; 90 L->last_tag++;
91 init_entry(L, L->last_tag); 91 init_entry(L, L->last_tag);
92 return L->last_tag; 92 return L->last_tag;
@@ -108,9 +108,9 @@ int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) {
108 int e; 108 int e;
109 checktag(L, tagto); 109 checktag(L, tagto);
110 checktag(L, tagfrom); 110 checktag(L, tagfrom);
111 for (e=0; e<IM_N; e++) { 111 for (e=0; e<TM_N; e++) {
112 if (luaT_validevent(tagto, e)) 112 if (luaT_validevent(tagto, e))
113 *luaT_getim(L, tagto, e) = *luaT_getim(L, tagfrom, e); 113 luaT_gettm(L, tagto, e) = luaT_gettm(L, tagfrom, e);
114 } 114 }
115 return tagto; 115 return tagto;
116} 116}
@@ -130,8 +130,10 @@ void lua_gettagmethod (lua_State *L, int t, const char *event) {
130 int e; 130 int e;
131 e = luaI_checkevent(L, event, t); 131 e = luaI_checkevent(L, event, t);
132 checktag(L, t); 132 checktag(L, t);
133 if (luaT_validevent(t, e)) 133 if (luaT_validevent(t, e) && luaT_gettm(L, t, e)) {
134 *L->top = *luaT_getim(L, t,e); 134 clvalue(L->top) = luaT_gettm(L, t, e);
135 ttype(L->top) = LUA_TFUNCTION;
136 }
135 else 137 else
136 ttype(L->top) = LUA_TNIL; 138 ttype(L->top) = LUA_TNIL;
137 incr_top; 139 incr_top;
@@ -139,19 +141,26 @@ void lua_gettagmethod (lua_State *L, int t, const char *event) {
139 141
140 142
141void lua_settagmethod (lua_State *L, int t, const char *event) { 143void lua_settagmethod (lua_State *L, int t, const char *event) {
142 TObject temp; 144 Closure *oldtm;
143 int e; 145 int e = luaI_checkevent(L, event, t);
144 LUA_ASSERT(lua_isnil(L, -1) || lua_isfunction(L, -1),
145 "function or nil expected");
146 e = luaI_checkevent(L, event, t);
147 checktag(L, t); 146 checktag(L, t);
148 if (!luaT_validevent(t, e)) 147 if (!luaT_validevent(t, e))
149 luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s", 148 luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s",
150 luaT_eventname[e], luaO_typenames[t], 149 luaT_eventname[e], luaO_typenames[t],
151 (t == LUA_TTABLE || t == LUA_TUSERDATA) ? " with default tag" 150 (t == LUA_TTABLE || t == LUA_TUSERDATA) ?
152 : ""); 151 " with default tag" : "");
153 temp = *(L->top - 1); 152 oldtm = luaT_gettm(L, t, e);
154 *(L->top - 1) = *luaT_getim(L, t,e); 153 switch (ttype(L->top - 1)) {
155 *luaT_getim(L, t, e) = temp; 154 case LUA_TNIL:
155 luaT_gettm(L, t, e) = NULL;
156 break;
157 case LUA_TFUNCTION:
158 luaT_gettm(L, t, e) = clvalue(L->top - 1);
159 break;
160 default:
161 lua_error(L, "tag method must be a function (or nil)");
162 }
163 clvalue(L->top - 1) = oldtm;
164 ttype(L->top - 1) = (oldtm ? LUA_TFUNCTION : LUA_TNIL);
156} 165}
157 166
diff --git a/ltm.h b/ltm.h
index c6de9e36..f72f9867 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 1.16 2000/10/03 14:27:44 roberto Exp roberto $ 2** $Id: ltm.h,v 1.17 2000/10/05 12:14:08 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -13,36 +13,36 @@
13 13
14/* 14/*
15* WARNING: if you change the order of this enumeration, 15* WARNING: if you change the order of this enumeration,
16* grep "ORDER IM" 16* grep "ORDER TM"
17*/ 17*/
18typedef enum { 18typedef enum {
19 IM_GETTABLE = 0, 19 TM_GETTABLE = 0,
20 IM_SETTABLE, 20 TM_SETTABLE,
21 IM_INDEX, 21 TM_INDEX,
22 IM_GETGLOBAL, 22 TM_GETGLOBAL,
23 IM_SETGLOBAL, 23 TM_SETGLOBAL,
24 IM_ADD, 24 TM_ADD,
25 IM_SUB, 25 TM_SUB,
26 IM_MUL, 26 TM_MUL,
27 IM_DIV, 27 TM_DIV,
28 IM_POW, 28 TM_POW,
29 IM_UNM, 29 TM_UNM,
30 IM_LT, 30 TM_LT,
31 IM_CONCAT, 31 TM_CONCAT,
32 IM_GC, 32 TM_GC,
33 IM_FUNCTION, 33 TM_FUNCTION,
34 IM_N /* number of elements in the enum */ 34 TM_N /* number of elements in the enum */
35} IMS; 35} TMS;
36 36
37 37
38struct IM { 38struct TM {
39 TObject int_method[IM_N]; 39 Closure *method[TM_N];
40 TString *collected; /* list of G. collected udata with this tag */ 40 TString *collected; /* list of garbage-collected udata with this tag */
41}; 41};
42 42
43 43
44#define luaT_getim(L,tag,event) (&L->IMtable[tag].int_method[event]) 44#define luaT_gettm(L,tag,event) (L->TMtable[tag].method[event])
45#define luaT_getimbyObj(L,o,e) (luaT_getim((L),luaT_tag(o),(e))) 45#define luaT_gettmbyObj(L,o,e) (luaT_gettm((L),luaT_tag(o),(e)))
46 46
47 47
48#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag) 48#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag)
diff --git a/lvm.c b/lvm.c
index 7b33be14..48f78d01 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.142 2000/10/04 12:16:08 roberto Exp roberto $ 2** $Id: lvm.c,v 1.143 2000/10/05 12:14:08 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -116,27 +116,27 @@ void luaV_Lclosure (lua_State *L, Proto *l, int nelems) {
116** Receives the table at `t' and the key at top. 116** Receives the table at `t' and the key at top.
117*/ 117*/
118const TObject *luaV_gettable (lua_State *L, StkId t) { 118const TObject *luaV_gettable (lua_State *L, StkId t) {
119 const TObject *im; 119 Closure *tm;
120 int tg; 120 int tg;
121 if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ 121 if (ttype(t) == LUA_TTABLE && /* `t' is a table? */
122 ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ 122 ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */
123 ttype(luaT_getim(L, tg, IM_GETTABLE)) == LUA_TNIL)) { /* or no TM? */ 123 luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */
124 /* do a primitive get */ 124 /* do a primitive get */
125 const TObject *h = luaH_get(L, hvalue(t), L->top-1); 125 const TObject *h = luaH_get(L, hvalue(t), L->top-1);
126 /* result is no nil or there is no `index' tag method? */ 126 /* result is no nil or there is no `index' tag method? */
127 if (ttype(h) != LUA_TNIL || 127 if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL))
128 (ttype(im=luaT_getim(L, tg, IM_INDEX)) == LUA_TNIL))
129 return h; /* return result */ 128 return h; /* return result */
130 /* else call `index' tag method */ 129 /* else call `index' tag method */
131 } 130 }
132 else { /* try a `gettable' tag method */ 131 else { /* try a `gettable' tag method */
133 im = luaT_getimbyObj(L, t, IM_GETTABLE); 132 tm = luaT_gettmbyObj(L, t, TM_GETTABLE);
134 } 133 }
135 if (ttype(im) != LUA_TNIL) { /* is there a tag method? */ 134 if (tm != NULL) { /* is there a tag method? */
136 luaD_checkstack(L, 2); 135 luaD_checkstack(L, 2);
137 *(L->top+1) = *(L->top-1); /* key */ 136 *(L->top+1) = *(L->top-1); /* key */
138 *L->top = *t; /* table */ 137 *L->top = *t; /* table */
139 *(L->top-1) = *im; /* tag method */ 138 clvalue(L->top-1) = tm; /* tag method */
139 ttype(L->top-1) = LUA_TFUNCTION;
140 L->top += 2; 140 L->top += 2;
141 luaD_call(L, L->top - 3, 1); 141 luaD_call(L, L->top - 3, 1);
142 return L->top - 1; /* call result */ 142 return L->top - 1; /* call result */
@@ -155,16 +155,17 @@ void luaV_settable (lua_State *L, StkId t, StkId key) {
155 int tg; 155 int tg;
156 if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ 156 if (ttype(t) == LUA_TTABLE && /* `t' is a table? */
157 ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ 157 ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */
158 ttype(luaT_getim(L, tg, IM_SETTABLE)) == LUA_TNIL)) /* or no TM? */ 158 luaT_gettm(L, tg, TM_SETTABLE) == NULL)) /* or no TM? */
159 *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */ 159 *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */
160 else { /* try a `settable' tag method */ 160 else { /* try a `settable' tag method */
161 const TObject *im = luaT_getimbyObj(L, t, IM_SETTABLE); 161 Closure *tm = luaT_gettmbyObj(L, t, TM_SETTABLE);
162 if (ttype(im) != LUA_TNIL) { 162 if (tm != NULL) {
163 luaD_checkstack(L, 3); 163 luaD_checkstack(L, 3);
164 *(L->top+2) = *(L->top-1); 164 *(L->top+2) = *(L->top-1);
165 *(L->top+1) = *key; 165 *(L->top+1) = *key;
166 *(L->top) = *t; 166 *(L->top) = *t;
167 *(L->top-1) = *im; 167 clvalue(L->top-1) = tm;
168 ttype(L->top-1) = LUA_TFUNCTION;
168 L->top += 3; 169 L->top += 3;
169 luaD_call(L, L->top - 4, 0); /* call `settable' tag method */ 170 luaD_call(L, L->top - 4, 0); /* call `settable' tag method */
170 } 171 }
@@ -176,14 +177,15 @@ void luaV_settable (lua_State *L, StkId t, StkId key) {
176 177
177const TObject *luaV_getglobal (lua_State *L, TString *s) { 178const TObject *luaV_getglobal (lua_State *L, TString *s) {
178 const TObject *value = luaH_getstr(L->gt, s); 179 const TObject *value = luaH_getstr(L->gt, s);
179 const TObject *im = luaT_getimbyObj(L, value, IM_GETGLOBAL); 180 Closure *tm = luaT_gettmbyObj(L, value, TM_GETGLOBAL);
180 if (ttype(im) == LUA_TNIL) /* is there a tag method? */ 181 if (tm == NULL) /* is there a tag method? */
181 return value; /* default behavior */ 182 return value; /* default behavior */
182 else { /* tag method */ 183 else { /* tag method */
183 luaD_checkstack(L, 3); 184 luaD_checkstack(L, 3);
184 *L->top = *im; 185 clvalue(L->top) = tm;
185 ttype(L->top+1) = LUA_TSTRING; 186 ttype(L->top) = LUA_TFUNCTION;
186 tsvalue(L->top+1) = s; /* global name */ 187 tsvalue(L->top+1) = s; /* global name */
188 ttype(L->top+1) = LUA_TSTRING;
187 *(L->top+2) = *value; 189 *(L->top+2) = *value;
188 L->top += 3; 190 L->top += 3;
189 luaD_call(L, L->top - 3, 1); 191 luaD_call(L, L->top - 3, 1);
@@ -194,8 +196,8 @@ const TObject *luaV_getglobal (lua_State *L, TString *s) {
194 196
195void luaV_setglobal (lua_State *L, TString *s) { 197void luaV_setglobal (lua_State *L, TString *s) {
196 const TObject *oldvalue = luaH_getstr(L->gt, s); 198 const TObject *oldvalue = luaH_getstr(L->gt, s);
197 const TObject *im = luaT_getimbyObj(L, oldvalue, IM_SETGLOBAL); 199 Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL);
198 if (ttype(im) == LUA_TNIL) { /* is there a tag method? */ 200 if (tm == NULL) { /* is there a tag method? */
199 if (oldvalue != &luaO_nilobject) { 201 if (oldvalue != &luaO_nilobject) {
200 /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */ 202 /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */
201 *(TObject *)oldvalue = *(L->top - 1); 203 *(TObject *)oldvalue = *(L->top - 1);
@@ -213,32 +215,33 @@ void luaV_setglobal (lua_State *L, TString *s) {
213 *(L->top+1) = *oldvalue; 215 *(L->top+1) = *oldvalue;
214 ttype(L->top) = LUA_TSTRING; 216 ttype(L->top) = LUA_TSTRING;
215 tsvalue(L->top) = s; 217 tsvalue(L->top) = s;
216 *(L->top-1) = *im; 218 clvalue(L->top-1) = tm;
219 ttype(L->top-1) = LUA_TFUNCTION;
217 L->top += 3; 220 L->top += 3;
218 luaD_call(L, L->top - 4, 0); 221 luaD_call(L, L->top - 4, 0);
219 } 222 }
220} 223}
221 224
222 225
223static int call_binTM (lua_State *L, StkId top, IMS event) { 226static int call_binTM (lua_State *L, StkId top, TMS event) {
224 /* try first operand */ 227 /* try first operand */
225 const TObject *im = luaT_getimbyObj(L, top-2, event); 228 Closure *tm = luaT_gettmbyObj(L, top-2, event);
226 L->top = top; 229 L->top = top;
227 if (ttype(im) == LUA_TNIL) { 230 if (tm == NULL) {
228 im = luaT_getimbyObj(L, top-1, event); /* try second operand */ 231 tm = luaT_gettmbyObj(L, top-1, event); /* try second operand */
229 if (ttype(im) == LUA_TNIL) { 232 if (tm == NULL) {
230 im = luaT_getim(L, 0, event); /* try a `global' method */ 233 tm = luaT_gettm(L, 0, event); /* try a `global' method */
231 if (ttype(im) == LUA_TNIL) 234 if (tm == NULL)
232 return 0; /* error */ 235 return 0; /* error */
233 } 236 }
234 } 237 }
235 lua_pushstring(L, luaT_eventname[event]); 238 lua_pushstring(L, luaT_eventname[event]);
236 luaD_callTM(L, im, 3, 1); 239 luaD_callTM(L, tm, 3, 1);
237 return 1; 240 return 1;
238} 241}
239 242
240 243
241static void call_arith (lua_State *L, StkId top, IMS event) { 244static void call_arith (lua_State *L, StkId top, TMS event) {
242 if (!call_binTM(L, top, event)) 245 if (!call_binTM(L, top, event))
243 luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on"); 246 luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on");
244} 247}
@@ -275,7 +278,7 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top)
275 luaD_checkstack(L, 2); 278 luaD_checkstack(L, 2);
276 *top++ = *l; 279 *top++ = *l;
277 *top++ = *r; 280 *top++ = *r;
278 if (!call_binTM(L, top, IM_LT)) 281 if (!call_binTM(L, top, TM_LT))
279 luaG_ordererror(L, top-2); 282 luaG_ordererror(L, top-2);
280 L->top--; 283 L->top--;
281 return (ttype(L->top) != LUA_TNIL); 284 return (ttype(L->top) != LUA_TNIL);
@@ -287,7 +290,7 @@ void luaV_strconc (lua_State *L, int total, StkId top) {
287 do { 290 do {
288 int n = 2; /* number of elements handled in this pass (at least 2) */ 291 int n = 2; /* number of elements handled in this pass (at least 2) */
289 if (tostring(L, top-2) || tostring(L, top-1)) { 292 if (tostring(L, top-2) || tostring(L, top-1)) {
290 if (!call_binTM(L, top, IM_CONCAT)) 293 if (!call_binTM(L, top, TM_CONCAT))
291 luaG_binerror(L, top-2, LUA_TSTRING, "concat"); 294 luaG_binerror(L, top-2, LUA_TSTRING, "concat");
292 } 295 }
293 else if (tsvalue(top-1)->u.s.len > 0) { /* if len=0, do nothing */ 296 else if (tsvalue(top-1)->u.s.len > 0) { /* if len=0, do nothing */
@@ -517,7 +520,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
517 } 520 }
518 case OP_ADD: { 521 case OP_ADD: {
519 if (tonumber(top-2) || tonumber(top-1)) 522 if (tonumber(top-2) || tonumber(top-1))
520 call_arith(L, top, IM_ADD); 523 call_arith(L, top, TM_ADD);
521 else 524 else
522 nvalue(top-2) += nvalue(top-1); 525 nvalue(top-2) += nvalue(top-1);
523 top--; 526 top--;
@@ -527,7 +530,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
527 if (tonumber(top-1)) { 530 if (tonumber(top-1)) {
528 ttype(top) = LUA_TNUMBER; 531 ttype(top) = LUA_TNUMBER;
529 nvalue(top) = (Number)GETARG_S(i); 532 nvalue(top) = (Number)GETARG_S(i);
530 call_arith(L, top+1, IM_ADD); 533 call_arith(L, top+1, TM_ADD);
531 } 534 }
532 else 535 else
533 nvalue(top-1) += (Number)GETARG_S(i); 536 nvalue(top-1) += (Number)GETARG_S(i);
@@ -535,7 +538,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
535 } 538 }
536 case OP_SUB: { 539 case OP_SUB: {
537 if (tonumber(top-2) || tonumber(top-1)) 540 if (tonumber(top-2) || tonumber(top-1))
538 call_arith(L, top, IM_SUB); 541 call_arith(L, top, TM_SUB);
539 else 542 else
540 nvalue(top-2) -= nvalue(top-1); 543 nvalue(top-2) -= nvalue(top-1);
541 top--; 544 top--;
@@ -543,7 +546,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
543 } 546 }
544 case OP_MULT: { 547 case OP_MULT: {
545 if (tonumber(top-2) || tonumber(top-1)) 548 if (tonumber(top-2) || tonumber(top-1))
546 call_arith(L, top, IM_MUL); 549 call_arith(L, top, TM_MUL);
547 else 550 else
548 nvalue(top-2) *= nvalue(top-1); 551 nvalue(top-2) *= nvalue(top-1);
549 top--; 552 top--;
@@ -551,14 +554,14 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
551 } 554 }
552 case OP_DIV: { 555 case OP_DIV: {
553 if (tonumber(top-2) || tonumber(top-1)) 556 if (tonumber(top-2) || tonumber(top-1))
554 call_arith(L, top, IM_DIV); 557 call_arith(L, top, TM_DIV);
555 else 558 else
556 nvalue(top-2) /= nvalue(top-1); 559 nvalue(top-2) /= nvalue(top-1);
557 top--; 560 top--;
558 break; 561 break;
559 } 562 }
560 case OP_POW: { 563 case OP_POW: {
561 if (!call_binTM(L, top, IM_POW)) 564 if (!call_binTM(L, top, TM_POW))
562 lua_error(L, "undefined operation"); 565 lua_error(L, "undefined operation");
563 top--; 566 top--;
564 break; 567 break;
@@ -574,7 +577,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
574 case OP_MINUS: { 577 case OP_MINUS: {
575 if (tonumber(top-1)) { 578 if (tonumber(top-1)) {
576 ttype(top) = LUA_TNIL; 579 ttype(top) = LUA_TNIL;
577 call_arith(L, top+1, IM_UNM); 580 call_arith(L, top+1, TM_UNM);
578 } 581 }
579 else 582 else
580 nvalue(top-1) = -nvalue(top-1); 583 nvalue(top-1) = -nvalue(top-1);