diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-05 18:15:18 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-12-05 18:15:18 -0200 |
commit | 592a309177edc52847b1196969ad6d49ba21f4fb (patch) | |
tree | 06add977885c012ee22cc4f105785c435b6af353 /lvm.c | |
parent | 413fc7334bf8ceaea71417d73edef15c99d3a793 (diff) | |
download | lua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.gz lua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.bz2 lua-592a309177edc52847b1196969ad6d49ba21f4fb.zip |
tag system replaced by event tables
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 137 |
1 files changed, 58 insertions, 79 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.198 2001/11/06 21:41:53 roberto Exp $ | 2 | ** $Id: lvm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -85,69 +85,66 @@ static void traceexec (lua_State *L, lua_Hook linehook) { | |||
85 | /* maximum stack used by a call to a tag method (func + args) */ | 85 | /* maximum stack used by a call to a tag method (func + args) */ |
86 | #define MAXSTACK_TM 4 | 86 | #define MAXSTACK_TM 4 |
87 | 87 | ||
88 | static StkId callTM (lua_State *L, Closure *f, const char *fmt, ...) { | 88 | static void callTM (lua_State *L, const TObject *f, |
89 | va_list argp; | 89 | const TObject *p1, const TObject *p2, const TObject *p3, TObject *result ) { |
90 | StkId base = L->top; | 90 | StkId base = L->top; |
91 | lua_assert(strlen(fmt)+1 <= MAXSTACK_TM); | ||
92 | luaD_checkstack(L, MAXSTACK_TM); | 91 | luaD_checkstack(L, MAXSTACK_TM); |
93 | va_start(argp, fmt); | 92 | setobj(base, f); /* push function */ |
94 | setclvalue(L->top, f); /* push function */ | 93 | setobj(base+1, p1); /* 1st argument */ |
95 | L->top++; | 94 | setobj(base+2, p2); /* 2nd argument */ |
96 | while (*fmt) { | 95 | L->top += 3; |
97 | if (*fmt++ == 'o') { | 96 | if (p3) { |
98 | setobj(L->top, va_arg(argp, TObject *)); | 97 | setobj(base+3, p3); /* 3th argument */ |
99 | } | ||
100 | else { | ||
101 | lua_assert(*(fmt-1) == 's'); | ||
102 | setsvalue(L->top, va_arg(argp, TString *)); | ||
103 | } | ||
104 | L->top++; | 98 | L->top++; |
105 | } | 99 | } |
106 | luaD_call(L, base); | 100 | luaD_call(L, base); |
107 | va_end(argp); | 101 | if (result) { /* need a result? */ |
108 | return base; | 102 | if (L->top == base) { /* are there valid results? */ |
109 | } | 103 | setnilvalue(result); /* function had no results */ |
110 | 104 | } | |
111 | 105 | else { | |
112 | #define setTM(L, base) (L->top = (base)) | 106 | setobj(result, base); /* get first result */ |
113 | 107 | } | |
114 | static void setTMresult (lua_State *L, TObject *result, StkId base) { | ||
115 | if (L->top == base) { /* are there valid results? */ | ||
116 | setnilvalue(result); /* function had no results */ | ||
117 | } | ||
118 | else { | ||
119 | setobj(result, base); /* get first result */ | ||
120 | } | 108 | } |
121 | L->top = base; /* restore top */ | 109 | L->top = base; /* restore top */ |
122 | } | 110 | } |
123 | 111 | ||
124 | 112 | ||
113 | |||
125 | /* | 114 | /* |
126 | ** Function to index a table. | 115 | ** Function to index a table. |
127 | ** Receives the table at `t' and the key at the `key'. | 116 | ** Receives the table at `t' and the key at the `key'. |
128 | ** leaves the result at `res'. | 117 | ** leaves the result at `res'. |
129 | */ | 118 | */ |
130 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | 119 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { |
131 | Closure *tm; | 120 | const TObject *tm; |
121 | init: | ||
132 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ | 122 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ |
133 | int tg = hvalue(t)->htag; | 123 | Table *et = hvalue(t)->eventtable; |
134 | if (tg == LUA_TTABLE || /* with default tag? */ | 124 | if ((tm = fasttm(L, et, TM_GETTABLE)) == NULL) { /* no gettable TM? */ |
135 | (tm = luaT_gettm(G(L), tg, TM_GETTABLE)) == NULL) { /* or no TM? */ | ||
136 | const TObject *h = luaH_get(hvalue(t), key); /* do a primitive get */ | 125 | const TObject *h = luaH_get(hvalue(t), key); /* do a primitive get */ |
137 | /* result is no nil or there is no `index' tag method? */ | 126 | /* result is no nil or there is no `index' tag method? */ |
138 | if (ttype(h) != LUA_TNIL || /* no nil? */ | 127 | if (ttype(h) != LUA_TNIL || /* no nil? */ |
139 | ((tm=luaT_gettm(G(L), tg, TM_INDEX)) == NULL)) { /* or no index TM? */ | 128 | (tm = fasttm(L, et, TM_INDEX)) == NULL) { /* or no index TM? */ |
140 | setobj(res, h); /* default get */ | 129 | setobj(res, h); /* default get */ |
141 | return; | 130 | return; |
142 | } | 131 | } |
143 | } | 132 | } |
144 | /* else will call the tag method */ | 133 | /* else will call the tag method */ |
145 | } else { /* not a table; try a `gettable' tag method */ | 134 | } else { /* not a table; try a `gettable' tag method */ |
146 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); | 135 | if (ttype(t) != LUA_TUSERDATA || |
147 | if (tm == NULL) /* no tag method? */ | 136 | (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_GETTABLE)) == NULL) { |
148 | luaG_typeerror(L, t, "index"); | 137 | luaG_typeerror(L, t, "index"); |
138 | return; /* to avoid warnings */ | ||
139 | } | ||
140 | } | ||
141 | lua_assert(tm != NULL); | ||
142 | if (ttype(tm) == LUA_TFUNCTION) | ||
143 | callTM(L, tm, t, key, NULL, res); | ||
144 | else { | ||
145 | t = tm; | ||
146 | goto init; /* return luaV_gettable(L, tm, key, res); */ | ||
149 | } | 147 | } |
150 | setTMresult(L, res, callTM(L, tm, "oo", t, key)); | ||
151 | } | 148 | } |
152 | 149 | ||
153 | 150 | ||
@@ -156,63 +153,44 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
156 | ** Receives table at `t', key at `key' and value at `val'. | 153 | ** Receives table at `t', key at `key' and value at `val'. |
157 | */ | 154 | */ |
158 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { | 155 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { |
159 | Closure *tm; | 156 | const TObject *tm; |
157 | init: | ||
160 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ | 158 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ |
161 | int tg = hvalue(t)->htag; | 159 | Table *et = hvalue(t)->eventtable; |
162 | if (hvalue(t)->htag == LUA_TTABLE || /* with default tag? */ | 160 | if ((tm = fasttm(L, et, TM_SETTABLE)) == NULL) { /* no TM? */ |
163 | (tm = luaT_gettm(G(L), tg, TM_SETTABLE)) == NULL) { /* or no TM? */ | ||
164 | luaH_set(L, hvalue(t), key, val); /* do a primitive set */ | 161 | luaH_set(L, hvalue(t), key, val); /* do a primitive set */ |
165 | return; | 162 | return; |
166 | } | 163 | } |
167 | /* else will call the tag method */ | 164 | /* else will call the tag method */ |
168 | } else { /* not a table; try a `settable' tag method */ | 165 | } else { /* not a table; try a `settable' tag method */ |
169 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); | 166 | if (ttype(t) != LUA_TUSERDATA || |
170 | if (tm == NULL) /* no tag method? */ | 167 | (tm = fasttm(L, uvalue(t)->uv.eventtable, TM_SETTABLE)) == NULL) { |
171 | luaG_typeerror(L, t, "index"); | 168 | luaG_typeerror(L, t, "index"); |
169 | return; /* to avoid warnings */ | ||
170 | } | ||
172 | } | 171 | } |
173 | setTM(L, callTM(L, tm, "ooo", t, key, val)); | 172 | lua_assert(tm != NULL); |
174 | } | 173 | if (ttype(tm) == LUA_TFUNCTION) |
175 | 174 | callTM(L, tm, t, key, val, NULL); | |
176 | 175 | else { | |
177 | void luaV_getglobal (lua_State *L, TString *name, StkId res) { | 176 | t = tm; |
178 | const TObject *value = luaH_getstr(hvalue(&L->gt), name); | 177 | goto init; /* luaV_settable(L, tm, key, val); */ |
179 | Closure *tm; | ||
180 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ | ||
181 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { | ||
182 | setobj(res, value); /* default behavior */ | ||
183 | } | ||
184 | else | ||
185 | setTMresult(L, res, callTM(L, tm, "so", name, value)); | ||
186 | } | ||
187 | |||
188 | |||
189 | void luaV_setglobal (lua_State *L, TString *name, StkId val) { | ||
190 | const TObject *oldvalue = luaH_getstr(hvalue(&L->gt), name); | ||
191 | Closure *tm; | ||
192 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ | ||
193 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { | ||
194 | if (oldvalue == &luaO_nilobject) | ||
195 | luaH_setstr(L, hvalue(&L->gt), name, val); /* raw set */ | ||
196 | else | ||
197 | settableval(oldvalue, val); /* warning: tricky optimization! */ | ||
198 | } | 178 | } |
199 | else | ||
200 | setTM(L, callTM(L, tm, "soo", name, oldvalue, val)); | ||
201 | } | 179 | } |
202 | 180 | ||
203 | 181 | ||
204 | static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | 182 | static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, |
205 | TObject *res, TMS event) { | 183 | TObject *res, TMS event) { |
206 | Closure *tm = luaT_gettmbyObj(G(L), p1, event); /* try first operand */ | 184 | const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ |
207 | if (tm == NULL) { | 185 | if (tm == NULL) { |
208 | tm = luaT_gettmbyObj(G(L), p2, event); /* try second operand */ | 186 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ |
209 | if (tm == NULL) { | 187 | if (tm == NULL) { |
210 | tm = luaT_gettm(G(L), 0, event); /* try a `global' method */ | 188 | tm = fasttm(L, hvalue(gt(L)), event); |
211 | if (tm == NULL) | 189 | if (tm == NULL) return 0; /* no tag method */ |
212 | return 0; /* no tag method */ | ||
213 | } | 190 | } |
214 | } | 191 | } |
215 | setTMresult(L, res, callTM(L, tm, "oo", p1, p2)); | 192 | if (ttype(tm) != LUA_TFUNCTION) return 0; |
193 | callTM(L, tm, p1, p2, NULL, res); | ||
216 | return 1; | 194 | return 1; |
217 | } | 195 | } |
218 | 196 | ||
@@ -295,12 +273,13 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
295 | static void luaV_pack (lua_State *L, StkId firstelem) { | 273 | static void luaV_pack (lua_State *L, StkId firstelem) { |
296 | int i; | 274 | int i; |
297 | Table *htab = luaH_new(L, 0, 0); | 275 | Table *htab = luaH_new(L, 0, 0); |
298 | TObject n; | 276 | TObject n, nname; |
299 | for (i=0; firstelem+i<L->top; i++) | 277 | for (i=0; firstelem+i<L->top; i++) |
300 | luaH_setnum(L, htab, i+1, firstelem+i); | 278 | luaH_setnum(L, htab, i+1, firstelem+i); |
301 | /* store counter in field `n' */ | 279 | /* store counter in field `n' */ |
302 | setnvalue(&n, i); | 280 | setnvalue(&n, i); |
303 | luaH_setstr(L, htab, luaS_newliteral(L, "n"), &n); | 281 | setsvalue(&nname, luaS_newliteral(L, "n")); |
282 | luaH_set(L, htab, &nname, &n); | ||
304 | L->top = firstelem; /* remove elements from the stack */ | 283 | L->top = firstelem; /* remove elements from the stack */ |
305 | sethvalue(L->top, htab); | 284 | sethvalue(L->top, htab); |
306 | incr_top; | 285 | incr_top; |
@@ -395,7 +374,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { | |||
395 | } | 374 | } |
396 | case OP_GETGLOBAL: { | 375 | case OP_GETGLOBAL: { |
397 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); | 376 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
398 | luaV_getglobal(L, tsvalue(KBc(i)), ra); | 377 | luaV_gettable(L, gt(L), KBc(i), ra); |
399 | break; | 378 | break; |
400 | } | 379 | } |
401 | case OP_GETTABLE: { | 380 | case OP_GETTABLE: { |
@@ -404,7 +383,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { | |||
404 | } | 383 | } |
405 | case OP_SETGLOBAL: { | 384 | case OP_SETGLOBAL: { |
406 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); | 385 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
407 | luaV_setglobal(L, tsvalue(KBc(i)), ra); | 386 | luaV_settable(L, gt(L), KBc(i), ra); |
408 | break; | 387 | break; |
409 | } | 388 | } |
410 | case OP_SETUPVAL: { | 389 | case OP_SETUPVAL: { |