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 /ltm.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 'ltm.c')
-rw-r--r-- | ltm.c | 165 |
1 files changed, 24 insertions, 141 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 1.80 2001/10/11 21:41:21 roberto Exp $ | 2 | ** $Id: ltm.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -10,8 +10,6 @@ | |||
10 | 10 | ||
11 | #include "lua.h" | 11 | #include "lua.h" |
12 | 12 | ||
13 | #include "ldo.h" | ||
14 | #include "lmem.h" | ||
15 | #include "lobject.h" | 13 | #include "lobject.h" |
16 | #include "lstate.h" | 14 | #include "lstate.h" |
17 | #include "lstring.h" | 15 | #include "lstring.h" |
@@ -19,161 +17,46 @@ | |||
19 | #include "ltm.h" | 17 | #include "ltm.h" |
20 | 18 | ||
21 | 19 | ||
22 | const char *const luaT_eventname[] = { /* ORDER TM */ | ||
23 | "gettable", "settable", "index", "getglobal", | ||
24 | "setglobal", "add", "sub", "mul", "div", | ||
25 | "pow", "unm", "lt", "concat", "gc", | ||
26 | "function", | ||
27 | NULL | ||
28 | }; | ||
29 | |||
30 | |||
31 | static int findevent (const char *name) { | ||
32 | int i; | ||
33 | for (i=0; luaT_eventname[i]; i++) | ||
34 | if (strcmp(luaT_eventname[i], name) == 0) | ||
35 | return i; | ||
36 | return -1; /* name not found */ | ||
37 | } | ||
38 | |||
39 | |||
40 | static int luaI_checkevent (lua_State *L, const char *name) { | ||
41 | int e = findevent(name); | ||
42 | if (e < 0) | ||
43 | luaO_verror(L, "`%.50s' is not a valid event name", name); | ||
44 | return e; | ||
45 | } | ||
46 | 20 | ||
47 | 21 | const char *const luaT_typenames[] = { | |
48 | 22 | "userdata", "nil", "number", "string", "table", "function" | |
49 | /* events in LUA_TNIL are all allowed, since this is used as a | ||
50 | * `placeholder' for default fallbacks | ||
51 | */ | ||
52 | /* ORDER LUA_T, ORDER TM */ | ||
53 | static const lu_byte luaT_validevents[NUM_TAGS][TM_N] = { | ||
54 | {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ | ||
55 | {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ | ||
56 | {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, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */ | ||
58 | {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */ | ||
59 | {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */ | ||
60 | }; | 23 | }; |
61 | 24 | ||
62 | static int luaT_validevent (int t, int e) { /* ORDER LUA_T */ | ||
63 | return (t >= NUM_TAGS) ? 1 : cast(int, luaT_validevents[t][e]); | ||
64 | } | ||
65 | |||
66 | 25 | ||
67 | void luaT_init (lua_State *L) { | 26 | void luaT_init (lua_State *L) { |
68 | static const char *const typenames[NUM_TAGS] = { | 27 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
69 | "userdata", "nil", "number", "string", | 28 | "gettable", "settable", "index", |
70 | "table", "function" | 29 | "gc", |
30 | "add", "sub", "mul", "div", | ||
31 | "pow", "unm", "lt", "concat", | ||
32 | "call" | ||
71 | }; | 33 | }; |
72 | int i; | 34 | int i; |
73 | for (i=0; i<NUM_TAGS; i++) | 35 | for (i=0; i<TM_N; i++) { |
74 | luaT_newtag(L, typenames[i], i); | 36 | G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); |
75 | } | 37 | G(L)->tmname[i]->tsv.marked = FIXMARK; /* never collect these names */ |
76 | |||
77 | |||
78 | int luaT_newtag (lua_State *L, const char *name, int basictype) { | ||
79 | int tag; | ||
80 | int i; | ||
81 | TString *ts = NULL; | ||
82 | luaM_growvector(L, G(L)->TMtable, G(L)->ntag, G(L)->sizeTM, struct TM, | ||
83 | MAX_INT, "tag table overflow"); | ||
84 | tag = G(L)->ntag; | ||
85 | if (name) { | ||
86 | const TObject *v; | ||
87 | TObject otag; | ||
88 | ts = luaS_new(L, name); | ||
89 | v = luaH_getstr(G(L)->type2tag, ts); | ||
90 | if (ttype(v) == LUA_TNUMBER) return cast(int, nvalue(v)); | ||
91 | setnvalue(&otag, tag); | ||
92 | luaH_setstr(L, G(L)->type2tag, ts, &otag); | ||
93 | } | 38 | } |
94 | for (i=0; i<TM_N; i++) | ||
95 | luaT_gettm(G(L), tag, i) = NULL; | ||
96 | G(L)->TMtable[tag].collected = NULL; | ||
97 | G(L)->TMtable[tag].name = ts; | ||
98 | G(L)->TMtable[tag].basictype = basictype; | ||
99 | G(L)->ntag++; | ||
100 | return tag; | ||
101 | } | ||
102 | |||
103 | |||
104 | static void checktag (lua_State *L, int tag) { | ||
105 | if (!(0 <= tag && tag < G(L)->ntag)) | ||
106 | luaO_verror(L, "%d is not a valid tag", tag); | ||
107 | } | 39 | } |
108 | 40 | ||
109 | 41 | ||
110 | int luaT_tag (const TObject *o) { | 42 | const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { |
111 | int t = ttype(o); | 43 | const TObject *tm = luaH_getstr(events, ename); |
112 | switch (t) { | 44 | if (ttype(tm) == LUA_TNIL) { /* no tag method? */ |
113 | case LUA_TUSERDATA: return uvalue(o)->uv.tag; | 45 | events->flags |= (1<<event); /* cache this fact */ |
114 | case LUA_TTABLE: return hvalue(o)->htag; | 46 | return NULL; |
115 | default: return t; | ||
116 | } | 47 | } |
48 | else return tm; | ||
117 | } | 49 | } |
118 | 50 | ||
119 | 51 | ||
120 | const char *luaT_typename (global_State *G, const TObject *o) { | 52 | const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) { |
121 | int t = ttype(o); | 53 | switch (ttype(o)) { |
122 | int tag; | ||
123 | TString *ts; | ||
124 | switch (t) { | ||
125 | case LUA_TUSERDATA: | ||
126 | tag = uvalue(o)->uv.tag; | ||
127 | break; | ||
128 | case LUA_TTABLE: | 54 | case LUA_TTABLE: |
129 | tag = hvalue(o)->htag; | 55 | return fasttm(L, hvalue(o)->eventtable, event); |
130 | break; | 56 | case LUA_TUSERDATA: |
131 | default: | 57 | return fasttm(L, uvalue(o)->uv.eventtable, event); |
132 | tag = t; | ||
133 | } | ||
134 | ts = G->TMtable[tag].name; | ||
135 | if (ts == NULL) | ||
136 | ts = G->TMtable[t].name; | ||
137 | return getstr(ts); | ||
138 | } | ||
139 | |||
140 | |||
141 | LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) { | ||
142 | int e; | ||
143 | lua_lock(L); | ||
144 | e = luaI_checkevent(L, event); | ||
145 | checktag(L, t); | ||
146 | if (luaT_validevent(t, e) && luaT_gettm(G(L), t, e)) { | ||
147 | setclvalue(L->top, luaT_gettm(G(L), t, e)); | ||
148 | } | ||
149 | else | ||
150 | setnilvalue(L->top); | ||
151 | incr_top; | ||
152 | lua_unlock(L); | ||
153 | } | ||
154 | |||
155 | |||
156 | LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) { | ||
157 | int e; | ||
158 | lua_lock(L); | ||
159 | e = luaI_checkevent(L, event); | ||
160 | checktag(L, t); | ||
161 | if (!luaT_validevent(t, e)) | ||
162 | luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s", | ||
163 | luaT_eventname[e], typenamebytag(G(L), t), | ||
164 | (t == LUA_TTABLE || t == LUA_TUSERDATA) ? | ||
165 | " with default tag" : ""); | ||
166 | switch (ttype(L->top - 1)) { | ||
167 | case LUA_TNIL: | ||
168 | luaT_gettm(G(L), t, e) = NULL; | ||
169 | break; | ||
170 | case LUA_TFUNCTION: | ||
171 | luaT_gettm(G(L), t, e) = clvalue(L->top - 1); | ||
172 | break; | ||
173 | default: | 58 | default: |
174 | luaD_error(L, "tag method must be a function (or nil)"); | 59 | return NULL; |
175 | } | 60 | } |
176 | L->top--; | ||
177 | lua_unlock(L); | ||
178 | } | 61 | } |
179 | 62 | ||