diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-05 10:00:17 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-10-05 10:00:17 -0300 |
commit | 046a3d6173792b7d4d4d26a4e063e2fe383c10a7 (patch) | |
tree | efe5a4544585084ab6e8d301847cc8568a1cc955 | |
parent | 001f2bdd0e2f8803889c1b5164b57a51e44aef5b (diff) | |
download | lua-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.c | 16 | ||||
-rw-r--r-- | ldo.c | 15 | ||||
-rw-r--r-- | ldo.h | 4 | ||||
-rw-r--r-- | lgc.c | 39 | ||||
-rw-r--r-- | lstate.c | 8 | ||||
-rw-r--r-- | lstate.h | 7 | ||||
-rw-r--r-- | ltests.c | 12 | ||||
-rw-r--r-- | ltm.c | 63 | ||||
-rw-r--r-- | ltm.h | 52 | ||||
-rw-r--r-- | lvm.c | 77 |
10 files changed, 161 insertions, 132 deletions
@@ -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 | ||
205 | static const char *travtagmethods (lua_State *L, const TObject *o) { | 205 | static 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 | } |
@@ -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 | ||
145 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults) { | 145 | void 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; |
@@ -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); | |||
25 | void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, | 25 | void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, |
26 | const char *event); | 26 | const char *event); |
27 | void luaD_call (lua_State *L, StkId func, int nResults); | 27 | void luaD_call (lua_State *L, StkId func, int nResults); |
28 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); | 28 | void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults); |
29 | void luaD_checkstack (lua_State *L, int n); | 29 | void luaD_checkstack (lua_State *L, int n); |
30 | 30 | ||
31 | void luaD_breakrun (lua_State *L, int errcode); | 31 | void luaD_breakrun (lua_State *L, int errcode); |
@@ -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 | ||
66 | static 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 | |||
76 | static void markclosure (GCState *st, Closure *cl) { | 66 | static 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 | ||
76 | static 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 | |||
86 | static void markobject (GCState *st, TObject *o) { | 88 | static 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 | ||
294 | static void callgcTM (lua_State *L, const TObject *o) { | 296 | static 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); |
@@ -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); |
@@ -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 | ||
34 | struct lua_longjmp; /* defined in ldo.c */ | 34 | struct lua_longjmp; /* defined in ldo.c */ |
35 | struct TM; /* defined in ltm.h */ | ||
35 | 36 | ||
36 | 37 | ||
37 | typedef struct stringtable { | 38 | typedef 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 */ |
@@ -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 | } |
@@ -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 | ||
20 | const char *const luaT_eventname[] = { /* ORDER IM */ | 20 | const 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 | ||
37 | static int luaI_checkevent (lua_State *L, const char *name, int t) { | 37 | static 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 */ |
54 | static const char luaT_validevents[NUM_TAGS][IM_N] = { | 54 | static 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 | ||
68 | static void init_entry (lua_State *L, int tag) { | 68 | static 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 | ||
76 | void luaT_init (lua_State *L) { | 76 | void 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 | ||
86 | int lua_newtag (lua_State *L) { | 86 | int 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 | ||
141 | void lua_settagmethod (lua_State *L, int t, const char *event) { | 143 | void 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 | ||
@@ -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 | */ |
18 | typedef enum { | 18 | typedef 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 | ||
38 | struct IM { | 38 | struct 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) |
@@ -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 | */ |
118 | const TObject *luaV_gettable (lua_State *L, StkId t) { | 118 | const 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 | ||
177 | const TObject *luaV_getglobal (lua_State *L, TString *s) { | 178 | const 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 | ||
195 | void luaV_setglobal (lua_State *L, TString *s) { | 197 | void 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 | ||
223 | static int call_binTM (lua_State *L, StkId top, IMS event) { | 226 | static 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 | ||
241 | static void call_arith (lua_State *L, StkId top, IMS event) { | 244 | static 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); |