diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:25:59 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:25:59 -0300 |
commit | 4b91e9cde630573cb35bb20101eb74cf5cf79a27 (patch) | |
tree | a3f4021ffcff5856633dfac5f1f3faa38e4ab0bf /ltm.c | |
parent | 26c5f56ad1ac6f0409e638f44af75da09f2b0a0b (diff) | |
download | lua-4b91e9cde630573cb35bb20101eb74cf5cf79a27.tar.gz lua-4b91e9cde630573cb35bb20101eb74cf5cf79a27.tar.bz2 lua-4b91e9cde630573cb35bb20101eb74cf5cf79a27.zip |
Tag methods
Diffstat (limited to 'ltm.c')
-rw-r--r-- | ltm.c | 317 |
1 files changed, 317 insertions, 0 deletions
@@ -0,0 +1,317 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** Tag methods | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | |||
11 | #include "lauxlib.h" | ||
12 | #include "ldo.h" | ||
13 | #include "lmem.h" | ||
14 | #include "lobject.h" | ||
15 | #include "ltm.h" | ||
16 | |||
17 | static struct IM init_IM[NUM_TYPES] = { | ||
18 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
19 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
20 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
21 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
22 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
23 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
24 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
25 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
26 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
27 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
28 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
29 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
30 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
31 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
32 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
33 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
34 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
35 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
36 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
37 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
38 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
39 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
40 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
41 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
42 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
43 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
44 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
45 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
46 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
47 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
48 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
49 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
50 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
51 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
52 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
53 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
54 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
55 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
56 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
57 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
58 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
59 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
60 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
61 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
62 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
63 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
64 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
65 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
66 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
67 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
68 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
69 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
70 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
71 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
72 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
73 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
74 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
75 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
76 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
77 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}}, | ||
78 | {{{LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
79 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
80 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
81 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
82 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, | ||
83 | {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}, {LUA_T_NIL, {NULL}}}} | ||
84 | }; | ||
85 | |||
86 | |||
87 | |||
88 | |||
89 | char *luaT_eventname[] = { /* ORDER IM */ | ||
90 | "gettable", "settable", "index", "getglobal", "setglobal", "add", | ||
91 | "sub", "mul", "div", "pow", "unm", "lt", "le", "gt", "ge", | ||
92 | "concat", "gc", "function", | ||
93 | NULL | ||
94 | }; | ||
95 | |||
96 | |||
97 | static int luaI_checkevent (char *name, char *list[]) | ||
98 | { | ||
99 | int e = luaO_findstring(name, list); | ||
100 | if (e < 0) | ||
101 | luaL_verror("`%.50s' is not a valid event name", name); | ||
102 | return e; | ||
103 | } | ||
104 | |||
105 | |||
106 | struct IM *luaT_IMtable = init_IM; | ||
107 | |||
108 | static int IMtable_size = NUM_TYPES; | ||
109 | |||
110 | static int last_tag = -(NUM_TYPES-1); | ||
111 | |||
112 | |||
113 | /* events in LUA_T_LINE are all allowed, since this is used as a | ||
114 | * 'placeholder' for "default" fallbacks | ||
115 | */ | ||
116 | static char validevents[NUM_TYPES][IM_N] = { /* ORDER LUA_T, ORDER IM */ | ||
117 | {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_T_USERDATA */ | ||
118 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_LINE */ | ||
119 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_CMARK */ | ||
120 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_MARK */ | ||
121 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_CFUNCTION */ | ||
122 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, /* LUA_T_FUNCTION */ | ||
123 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* LUA_T_PROTO */ | ||
124 | {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_T_ARRAY */ | ||
125 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_STRING */ | ||
126 | {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_T_NUMBER */ | ||
127 | {1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} /* LUA_T_NIL */ | ||
128 | }; | ||
129 | |||
130 | static int validevent (lua_Type t, int e) | ||
131 | { /* ORDER LUA_T */ | ||
132 | return (t < LUA_T_NIL) ? 1 : validevents[-t][e]; | ||
133 | } | ||
134 | |||
135 | |||
136 | static void init_entry (int tag) | ||
137 | { | ||
138 | int i; | ||
139 | for (i=0; i<IM_N; i++) | ||
140 | ttype(luaT_getim(tag, i)) = LUA_T_NIL; | ||
141 | } | ||
142 | |||
143 | int lua_newtag (void) | ||
144 | { | ||
145 | --last_tag; | ||
146 | if ((-last_tag) >= IMtable_size) { | ||
147 | if (luaT_IMtable == init_IM) { /* fist time? */ | ||
148 | IMtable_size *= 2; | ||
149 | luaT_IMtable = luaM_newvector(IMtable_size, struct IM); | ||
150 | memcpy(luaT_IMtable, init_IM, sizeof(init_IM)); | ||
151 | } | ||
152 | else | ||
153 | IMtable_size = luaM_growvector(&luaT_IMtable, IMtable_size, | ||
154 | struct IM, memEM, MAX_INT); | ||
155 | } | ||
156 | init_entry(last_tag); | ||
157 | return last_tag; | ||
158 | } | ||
159 | |||
160 | |||
161 | static void checktag (int tag) | ||
162 | { /* ORDER LUA_T */ | ||
163 | if (!(last_tag <= tag && tag <= 0)) | ||
164 | luaL_verror("%d is not a valid tag", tag); | ||
165 | } | ||
166 | |||
167 | void luaT_realtag (int tag) | ||
168 | { | ||
169 | if (!(last_tag <= tag && tag < LUA_T_NIL)) | ||
170 | luaL_verror("tag %d is not result of `newtag'", tag); | ||
171 | } | ||
172 | |||
173 | |||
174 | |||
175 | int luaT_efectivetag (TObject *o) | ||
176 | { | ||
177 | lua_Type t = ttype(o); | ||
178 | if (t == LUA_T_USERDATA) { | ||
179 | int tag = o->value.ts->tag; | ||
180 | return (tag >= 0) ? LUA_T_USERDATA : tag; | ||
181 | } | ||
182 | else if (t == LUA_T_ARRAY) | ||
183 | return o->value.a->htag; | ||
184 | else return t; | ||
185 | } | ||
186 | |||
187 | |||
188 | TObject *luaT_gettagmethod (int t, char *event) | ||
189 | { | ||
190 | int e = luaI_checkevent(event, luaT_eventname); | ||
191 | checktag(t); | ||
192 | if (validevent(t, e)) | ||
193 | return luaT_getim(t,e); | ||
194 | else | ||
195 | return luaT_getim(LUA_T_CMARK, IM_GETTABLE); /* always nil */ | ||
196 | } | ||
197 | |||
198 | |||
199 | void luaT_settagmethod (int t, char *event, TObject *func) | ||
200 | { | ||
201 | TObject temp = *func; | ||
202 | int e = luaI_checkevent(event, luaT_eventname); | ||
203 | checktag(t); | ||
204 | if (!validevent(t, e)) | ||
205 | luaL_verror("settagmethod: cannot change internal method `%s' for tag %d", | ||
206 | luaT_eventname[e], t); | ||
207 | *func = *luaT_getim(t,e); | ||
208 | *luaT_getim(t, e) = temp; | ||
209 | } | ||
210 | |||
211 | |||
212 | char *luaT_travtagmethods (int (*fn)(TObject *)) | ||
213 | { | ||
214 | int e; | ||
215 | if (fn(&luaD_errorim)) | ||
216 | return "error"; | ||
217 | for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { /* ORDER IM */ | ||
218 | int t; | ||
219 | for (t=0; t>=last_tag; t--) | ||
220 | if (fn(luaT_getim(t,e))) | ||
221 | return luaT_eventname[e]; | ||
222 | } | ||
223 | return NULL; | ||
224 | } | ||
225 | |||
226 | |||
227 | /* | ||
228 | * =================================================================== | ||
229 | * compatibility with old fallback system | ||
230 | */ | ||
231 | #if LUA_COMPAT2_5 | ||
232 | |||
233 | #include "lapi.h" | ||
234 | |||
235 | static void errorFB (void) | ||
236 | { | ||
237 | lua_Object o = lua_getparam(1); | ||
238 | if (lua_isstring(o)) | ||
239 | fprintf(stderr, "lua: %s\n", lua_getstring(o)); | ||
240 | else | ||
241 | fprintf(stderr, "lua: unknown error\n"); | ||
242 | } | ||
243 | |||
244 | |||
245 | static void nilFB (void) { } | ||
246 | |||
247 | |||
248 | static void typeFB (void) | ||
249 | { | ||
250 | lua_error("unexpected type"); | ||
251 | } | ||
252 | |||
253 | |||
254 | static void fillvalids (IMS e, TObject *func) | ||
255 | { | ||
256 | int t; | ||
257 | for (t=LUA_T_NIL; t<=LUA_T_USERDATA; t++) | ||
258 | if (validevent(t, e)) | ||
259 | *luaT_getim(t, e) = *func; | ||
260 | } | ||
261 | |||
262 | |||
263 | void luaT_setfallback (void) | ||
264 | { | ||
265 | static char *oldnames [] = {"error", "getglobal", "arith", "order", NULL}; | ||
266 | TObject oldfunc; | ||
267 | lua_CFunction replace; | ||
268 | char *name = luaL_check_string(1); | ||
269 | lua_Object func = lua_getparam(2); | ||
270 | luaL_arg_check(lua_isfunction(func), 2, "function expected"); | ||
271 | switch (luaO_findstring(name, oldnames)) { | ||
272 | case 0: /* old error fallback */ | ||
273 | oldfunc = luaD_errorim; | ||
274 | luaD_errorim = *luaA_Address(func); | ||
275 | replace = errorFB; | ||
276 | break; | ||
277 | case 1: /* old getglobal fallback */ | ||
278 | oldfunc = *luaT_getim(LUA_T_NIL, IM_GETGLOBAL); | ||
279 | *luaT_getim(LUA_T_NIL, IM_GETGLOBAL) = *luaA_Address(func); | ||
280 | replace = nilFB; | ||
281 | break; | ||
282 | case 2: { /* old arith fallback */ | ||
283 | int i; | ||
284 | oldfunc = *luaT_getim(LUA_T_NUMBER, IM_POW); | ||
285 | for (i=IM_ADD; i<=IM_UNM; i++) /* ORDER IM */ | ||
286 | fillvalids(i, luaA_Address(func)); | ||
287 | replace = typeFB; | ||
288 | break; | ||
289 | } | ||
290 | case 3: { /* old order fallback */ | ||
291 | int i; | ||
292 | oldfunc = *luaT_getim(LUA_T_LINE, IM_LT); | ||
293 | for (i=IM_LT; i<=IM_GE; i++) /* ORDER IM */ | ||
294 | fillvalids(i, luaA_Address(func)); | ||
295 | replace = typeFB; | ||
296 | break; | ||
297 | } | ||
298 | default: { | ||
299 | int e; | ||
300 | if ((e = luaO_findstring(name, luaT_eventname)) >= 0) { | ||
301 | oldfunc = *luaT_getim(LUA_T_LINE, e); | ||
302 | fillvalids(e, luaA_Address(func)); | ||
303 | replace = (e == IM_GC || e == IM_INDEX) ? nilFB : typeFB; | ||
304 | } | ||
305 | else { | ||
306 | luaL_verror("`%.50s' is not a valid fallback name", name); | ||
307 | replace = NULL; /* to avoid warnings */ | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | if (oldfunc.ttype != LUA_T_NIL) | ||
312 | luaA_pushobject(&oldfunc); | ||
313 | else | ||
314 | lua_pushcfunction(replace); | ||
315 | } | ||
316 | #endif | ||
317 | |||