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 | |
parent | 413fc7334bf8ceaea71417d73edef15c99d3a793 (diff) | |
download | lua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.gz lua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.bz2 lua-592a309177edc52847b1196969ad6d49ba21f4fb.zip |
tag system replaced by event tables
-rw-r--r-- | lapi.c | 150 | ||||
-rw-r--r-- | lauxlib.c | 19 | ||||
-rw-r--r-- | lauxlib.h | 6 | ||||
-rw-r--r-- | lbaselib.c | 138 | ||||
-rw-r--r-- | ldebug.c | 29 | ||||
-rw-r--r-- | ldo.c | 21 | ||||
-rw-r--r-- | lfunc.c | 4 | ||||
-rw-r--r-- | lgc.c | 121 | ||||
-rw-r--r-- | lgc.h | 4 | ||||
-rw-r--r-- | liolib.c | 58 | ||||
-rw-r--r-- | lmathlib.c | 5 | ||||
-rw-r--r-- | lobject.h | 22 | ||||
-rw-r--r-- | lstate.c | 21 | ||||
-rw-r--r-- | lstate.h | 34 | ||||
-rw-r--r-- | lstring.c | 8 | ||||
-rw-r--r-- | lstrlib.c | 4 | ||||
-rw-r--r-- | ltable.c | 19 | ||||
-rw-r--r-- | ltable.h | 3 | ||||
-rw-r--r-- | ltests.c | 61 | ||||
-rw-r--r-- | ltm.c | 165 | ||||
-rw-r--r-- | ltm.h | 49 | ||||
-rw-r--r-- | lua.h | 36 | ||||
-rw-r--r-- | lvm.c | 137 | ||||
-rw-r--r-- | lvm.h | 4 |
24 files changed, 412 insertions, 706 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 1.160 2001/11/16 16:29:51 roberto Exp $ | 2 | ** $Id: lapi.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -45,8 +45,8 @@ static TObject *negindex (lua_State *L, int index) { | |||
45 | return L->top+index; | 45 | return L->top+index; |
46 | } | 46 | } |
47 | else switch (index) { /* pseudo-indices */ | 47 | else switch (index) { /* pseudo-indices */ |
48 | case LUA_REGISTRYINDEX: return &G(L)->registry; | 48 | case LUA_REGISTRYINDEX: return registry(L); |
49 | case LUA_GLOBALSINDEX: return &L->gt; | 49 | case LUA_GLOBALSINDEX: return gt(L); |
50 | default: { | 50 | default: { |
51 | TObject *func = (L->ci->base - 1); | 51 | TObject *func = (L->ci->base - 1); |
52 | index = LUA_GLOBALSINDEX - index; | 52 | index = LUA_GLOBALSINDEX - index; |
@@ -149,20 +149,15 @@ LUA_API void lua_pushvalue (lua_State *L, int index) { | |||
149 | */ | 149 | */ |
150 | 150 | ||
151 | 151 | ||
152 | LUA_API int lua_rawtag (lua_State *L, int index) { | 152 | LUA_API int lua_type (lua_State *L, int index) { |
153 | StkId o = luaA_indexAcceptable(L, index); | 153 | StkId o = luaA_indexAcceptable(L, index); |
154 | return (o == NULL) ? LUA_TNONE : ttype(o); | 154 | return (o == NULL) ? LUA_TNONE : ttype(o); |
155 | } | 155 | } |
156 | 156 | ||
157 | 157 | ||
158 | LUA_API const char *lua_type (lua_State *L, int index) { | 158 | LUA_API const char *lua_typename (lua_State *L, int t) { |
159 | StkId o; | 159 | UNUSED(L); |
160 | const char *type; | 160 | return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; |
161 | lua_lock(L); | ||
162 | o = luaA_indexAcceptable(L, index); | ||
163 | type = (o == NULL) ? "no value" : luaT_typename(G(L), o); | ||
164 | lua_unlock(L); | ||
165 | return type; | ||
166 | } | 161 | } |
167 | 162 | ||
168 | 163 | ||
@@ -180,22 +175,11 @@ LUA_API int lua_isnumber (lua_State *L, int index) { | |||
180 | 175 | ||
181 | 176 | ||
182 | LUA_API int lua_isstring (lua_State *L, int index) { | 177 | LUA_API int lua_isstring (lua_State *L, int index) { |
183 | int t = lua_rawtag(L, index); | 178 | int t = lua_type(L, index); |
184 | return (t == LUA_TSTRING || t == LUA_TNUMBER); | 179 | return (t == LUA_TSTRING || t == LUA_TNUMBER); |
185 | } | 180 | } |
186 | 181 | ||
187 | 182 | ||
188 | LUA_API int lua_tag (lua_State *L, int index) { | ||
189 | StkId o; | ||
190 | int i; | ||
191 | lua_lock(L); /* other thread could be changing the tag */ | ||
192 | o = luaA_indexAcceptable(L, index); | ||
193 | i = (o == NULL) ? LUA_NOTAG : luaT_tag(o); | ||
194 | lua_unlock(L); | ||
195 | return i; | ||
196 | } | ||
197 | |||
198 | |||
199 | LUA_API int lua_equal (lua_State *L, int index1, int index2) { | 183 | LUA_API int lua_equal (lua_State *L, int index1, int index2) { |
200 | StkId o1 = luaA_indexAcceptable(L, index1); | 184 | StkId o1 = luaA_indexAcceptable(L, index1); |
201 | StkId o2 = luaA_indexAcceptable(L, index2); | 185 | StkId o2 = luaA_indexAcceptable(L, index2); |
@@ -346,8 +330,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
346 | 330 | ||
347 | 331 | ||
348 | LUA_API void lua_getglobal (lua_State *L, const char *name) { | 332 | LUA_API void lua_getglobal (lua_State *L, const char *name) { |
333 | TObject o; | ||
349 | lua_lock(L); | 334 | lua_lock(L); |
350 | luaV_getglobal(L, luaS_new(L, name), L->top); | 335 | setsvalue(&o, luaS_new(L, name)); |
336 | luaV_gettable(L, gt(L), &o, L->top); | ||
351 | api_incr_top(L); | 337 | api_incr_top(L); |
352 | lua_unlock(L); | 338 | lua_unlock(L); |
353 | } | 339 | } |
@@ -391,6 +377,29 @@ LUA_API void lua_newtable (lua_State *L) { | |||
391 | } | 377 | } |
392 | 378 | ||
393 | 379 | ||
380 | LUA_API void lua_geteventtable (lua_State *L, int objindex) { | ||
381 | StkId obj; | ||
382 | Table *et; | ||
383 | lua_lock(L); | ||
384 | obj = luaA_indexAcceptable(L, objindex); | ||
385 | switch (ttype(obj)) { | ||
386 | case LUA_TTABLE: | ||
387 | et = hvalue(obj)->eventtable; | ||
388 | break; | ||
389 | case LUA_TUSERDATA: | ||
390 | et = uvalue(obj)->uv.eventtable; | ||
391 | break; | ||
392 | default: | ||
393 | et = hvalue(defaultet(L)); | ||
394 | } | ||
395 | if (et == hvalue(defaultet(L))) | ||
396 | setnilvalue(L->top); | ||
397 | else | ||
398 | sethvalue(L->top, et); | ||
399 | api_incr_top(L); | ||
400 | lua_unlock(L); | ||
401 | } | ||
402 | |||
394 | 403 | ||
395 | /* | 404 | /* |
396 | ** set functions (stack -> Lua) | 405 | ** set functions (stack -> Lua) |
@@ -398,9 +407,11 @@ LUA_API void lua_newtable (lua_State *L) { | |||
398 | 407 | ||
399 | 408 | ||
400 | LUA_API void lua_setglobal (lua_State *L, const char *name) { | 409 | LUA_API void lua_setglobal (lua_State *L, const char *name) { |
410 | TObject o; | ||
401 | lua_lock(L); | 411 | lua_lock(L); |
402 | api_checknelems(L, 1); | 412 | api_checknelems(L, 1); |
403 | luaV_setglobal(L, luaS_new(L, name), L->top - 1); | 413 | setsvalue(&o, luaS_new(L, name)); |
414 | luaV_settable(L, gt(L), &o, L->top - 1); | ||
404 | L->top--; /* remove element from the top */ | 415 | L->top--; /* remove element from the top */ |
405 | lua_unlock(L); | 416 | lua_unlock(L); |
406 | } | 417 | } |
@@ -447,11 +458,32 @@ LUA_API void lua_setglobals (lua_State *L) { | |||
447 | api_checknelems(L, 1); | 458 | api_checknelems(L, 1); |
448 | newtable = --L->top; | 459 | newtable = --L->top; |
449 | api_check(L, ttype(newtable) == LUA_TTABLE); | 460 | api_check(L, ttype(newtable) == LUA_TTABLE); |
450 | setobj(&L->gt, newtable); | 461 | setobj(gt(L), newtable); |
451 | lua_unlock(L); | 462 | lua_unlock(L); |
452 | } | 463 | } |
453 | 464 | ||
454 | 465 | ||
466 | LUA_API void lua_seteventtable (lua_State *L, int objindex) { | ||
467 | StkId obj, et; | ||
468 | lua_lock(L); | ||
469 | api_checknelems(L, 1); | ||
470 | obj = luaA_indexAcceptable(L, objindex); | ||
471 | et = --L->top; | ||
472 | api_check(L, ttype(et) == LUA_TTABLE); | ||
473 | switch (ttype(obj)) { | ||
474 | case LUA_TTABLE: | ||
475 | hvalue(obj)->eventtable = hvalue(et); | ||
476 | break; | ||
477 | case LUA_TUSERDATA: | ||
478 | uvalue(obj)->uv.eventtable = hvalue(et); | ||
479 | break; | ||
480 | default: | ||
481 | luaO_verror(L, "cannot change the event table of a %.20s", | ||
482 | luaT_typenames[ttype(obj)]); | ||
483 | } | ||
484 | lua_unlock(L); | ||
485 | } | ||
486 | |||
455 | 487 | ||
456 | /* | 488 | /* |
457 | ** `do' functions (run Lua code) | 489 | ** `do' functions (run Lua code) |
@@ -533,70 +565,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { | |||
533 | ** miscellaneous functions | 565 | ** miscellaneous functions |
534 | */ | 566 | */ |
535 | 567 | ||
536 | LUA_API int lua_newtype (lua_State *L, const char *name, int basictype) { | ||
537 | int tag; | ||
538 | lua_lock(L); | ||
539 | if (basictype != LUA_TNONE && | ||
540 | basictype != LUA_TTABLE && | ||
541 | basictype != LUA_TUSERDATA) | ||
542 | luaO_verror(L, "invalid basic type (%d) for new type", basictype); | ||
543 | tag = luaT_newtag(L, name, basictype); | ||
544 | if (tag == LUA_TNONE) | ||
545 | luaO_verror(L, "type name '%.30s' already exists", name); | ||
546 | lua_unlock(L); | ||
547 | return tag; | ||
548 | } | ||
549 | |||
550 | |||
551 | LUA_API int lua_name2tag (lua_State *L, const char *name) { | ||
552 | int tag; | ||
553 | const TObject *v; | ||
554 | lua_lock(L); | ||
555 | v = luaH_getstr(G(L)->type2tag, luaS_new(L, name)); | ||
556 | if (ttype(v) == LUA_TNIL) | ||
557 | tag = LUA_TNONE; | ||
558 | else { | ||
559 | lua_assert(ttype(v) == LUA_TNUMBER); | ||
560 | tag = cast(int, nvalue(v)); | ||
561 | } | ||
562 | lua_unlock(L); | ||
563 | return tag; | ||
564 | } | ||
565 | |||
566 | |||
567 | LUA_API const char *lua_tag2name (lua_State *L, int tag) { | ||
568 | const char *s; | ||
569 | lua_lock(L); | ||
570 | s = (tag == LUA_TNONE) ? "no value" : typenamebytag(G(L), tag); | ||
571 | lua_unlock(L); | ||
572 | return s; | ||
573 | } | ||
574 | |||
575 | |||
576 | LUA_API void lua_settag (lua_State *L, int tag) { | ||
577 | int basictype; | ||
578 | lua_lock(L); | ||
579 | api_checknelems(L, 1); | ||
580 | if (tag < 0 || tag >= G(L)->ntag) | ||
581 | luaO_verror(L, "%d is not a valid tag", tag); | ||
582 | basictype = G(L)->TMtable[tag].basictype; | ||
583 | if (basictype != LUA_TNONE && basictype != ttype(L->top-1)) | ||
584 | luaO_verror(L, "tag %d can only be used for type '%.20s'", tag, | ||
585 | typenamebytag(G(L), basictype)); | ||
586 | switch (ttype(L->top-1)) { | ||
587 | case LUA_TTABLE: | ||
588 | hvalue(L->top-1)->htag = tag; | ||
589 | break; | ||
590 | case LUA_TUSERDATA: | ||
591 | uvalue(L->top-1)->uv.tag = tag; | ||
592 | break; | ||
593 | default: | ||
594 | luaO_verror(L, "cannot change the tag of a %.20s", | ||
595 | luaT_typename(G(L), L->top-1)); | ||
596 | } | ||
597 | lua_unlock(L); | ||
598 | } | ||
599 | |||
600 | 568 | ||
601 | LUA_API void lua_error (lua_State *L, const char *s) { | 569 | LUA_API void lua_error (lua_State *L, const char *s) { |
602 | lua_lock(L); | 570 | lua_lock(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.c,v 1.53 2001/10/31 19:40:14 roberto Exp $ | 2 | ** $Id: lauxlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -43,7 +43,8 @@ LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |||
43 | 43 | ||
44 | LUALIB_API void luaL_typerror (lua_State *L, int narg, const char *tname) { | 44 | LUALIB_API void luaL_typerror (lua_State *L, int narg, const char *tname) { |
45 | char buff[80]; | 45 | char buff[80]; |
46 | sprintf(buff, "%.25s expected, got %.25s", tname, lua_type(L,narg)); | 46 | sprintf(buff, "%.25s expected, got %.25s", tname, |
47 | lua_typename(L, lua_type(L,narg))); | ||
47 | luaL_argerror(L, narg, buff); | 48 | luaL_argerror(L, narg, buff); |
48 | } | 49 | } |
49 | 50 | ||
@@ -59,26 +60,18 @@ LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) { | |||
59 | } | 60 | } |
60 | 61 | ||
61 | 62 | ||
62 | LUALIB_API void luaL_check_rawtype(lua_State *L, int narg, int t) { | 63 | LUALIB_API void luaL_check_type(lua_State *L, int narg, int t) { |
63 | if (lua_rawtag(L, narg) != t) | 64 | if (lua_type(L, narg) != t) |
64 | tag_error(L, narg, t); | 65 | tag_error(L, narg, t); |
65 | } | 66 | } |
66 | 67 | ||
67 | 68 | ||
68 | LUALIB_API void luaL_check_any (lua_State *L, int narg) { | 69 | LUALIB_API void luaL_check_any (lua_State *L, int narg) { |
69 | if (lua_rawtag(L, narg) == LUA_TNONE) | 70 | if (lua_type(L, narg) == LUA_TNONE) |
70 | luaL_argerror(L, narg, "value expected"); | 71 | luaL_argerror(L, narg, "value expected"); |
71 | } | 72 | } |
72 | 73 | ||
73 | 74 | ||
74 | LUALIB_API void *luaL_check_userdata (lua_State *L, int narg, | ||
75 | const char *name) { | ||
76 | if (strcmp(lua_type(L, narg), name) != 0) | ||
77 | luaL_typerror(L, narg, name); | ||
78 | return lua_touserdata(L, narg); | ||
79 | } | ||
80 | |||
81 | |||
82 | LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { | 75 | LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { |
83 | const char *s = lua_tostring(L, narg); | 76 | const char *s = lua_tostring(L, narg); |
84 | if (!s) tag_error(L, narg, LUA_TSTRING); | 77 | if (!s) tag_error(L, narg, LUA_TSTRING); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lauxlib.h,v 1.38 2001/10/31 19:40:14 roberto Exp $ | 2 | ** $Id: lauxlib.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -38,10 +38,8 @@ LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg); | |||
38 | LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def); | 38 | LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def); |
39 | 39 | ||
40 | LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg); | 40 | LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg); |
41 | LUALIB_API void luaL_check_rawtype (lua_State *L, int narg, int t); | 41 | LUALIB_API void luaL_check_type (lua_State *L, int narg, int t); |
42 | LUALIB_API void luaL_check_any (lua_State *L, int narg); | 42 | LUALIB_API void luaL_check_any (lua_State *L, int narg); |
43 | LUALIB_API void *luaL_check_userdata (lua_State *L, int narg, | ||
44 | const char *name); | ||
45 | 43 | ||
46 | LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); | 44 | LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); |
47 | LUALIB_API int luaL_findstring (const char *name, | 45 | LUALIB_API int luaL_findstring (const char *name, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.45 2001/10/26 17:33:30 roberto Exp $ | 2 | ** $Id: lbaselib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -41,7 +41,7 @@ static int luaB__ALERT (lua_State *L) { | |||
41 | ** The library `liolib' redefines _ERRORMESSAGE for better error information. | 41 | ** The library `liolib' redefines _ERRORMESSAGE for better error information. |
42 | */ | 42 | */ |
43 | static int luaB__ERRORMESSAGE (lua_State *L) { | 43 | static int luaB__ERRORMESSAGE (lua_State *L) { |
44 | luaL_check_rawtype(L, 1, LUA_TSTRING); | 44 | luaL_check_type(L, 1, LUA_TSTRING); |
45 | lua_getglobal(L, LUA_ALERT); | 45 | lua_getglobal(L, LUA_ALERT); |
46 | if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ | 46 | if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ |
47 | lua_Debug ar; | 47 | lua_Debug ar; |
@@ -136,41 +136,22 @@ static int luaB_getglobal (lua_State *L) { | |||
136 | } | 136 | } |
137 | 137 | ||
138 | 138 | ||
139 | /* auxiliary function to get `tags' */ | 139 | static int luaB_eventtable (lua_State *L) { |
140 | static int gettag (lua_State *L, int narg) { | 140 | luaL_check_type(L, 1, LUA_TTABLE); |
141 | switch (lua_rawtag(L, narg)) { | 141 | if (lua_isnull(L, 2)) |
142 | case LUA_TNUMBER: | 142 | lua_geteventtable(L, 1); |
143 | return (int)(lua_tonumber(L, narg)); | 143 | else { |
144 | case LUA_TSTRING: { | 144 | lua_settop(L, 2); |
145 | const char *name = lua_tostring(L, narg); | 145 | luaL_check_type(L, 2, LUA_TTABLE); |
146 | int tag = lua_name2tag(L, name); | 146 | lua_seteventtable(L, 1); |
147 | if (tag == LUA_TNONE) | ||
148 | luaL_verror(L, "'%.30s' is not a valid type name", name); | ||
149 | return tag; | ||
150 | } | ||
151 | default: | ||
152 | luaL_argerror(L, narg, "tag or type name expected"); | ||
153 | return 0; /* to avoid warnings */ | ||
154 | } | 147 | } |
155 | } | ||
156 | |||
157 | |||
158 | static int luaB_tag (lua_State *L) { | ||
159 | luaL_check_any(L, 1); | ||
160 | lua_pushnumber(L, lua_tag(L, 1)); | ||
161 | return 1; | 148 | return 1; |
162 | } | 149 | } |
163 | 150 | ||
164 | static int luaB_settype (lua_State *L) { | ||
165 | luaL_check_rawtype(L, 1, LUA_TTABLE); | ||
166 | lua_pushvalue(L, 1); /* push table */ | ||
167 | lua_settag(L, gettag(L, 2)); | ||
168 | return 1; /* return table */ | ||
169 | } | ||
170 | 151 | ||
171 | static int luaB_weakmode (lua_State *L) { | 152 | static int luaB_weakmode (lua_State *L) { |
172 | const char *mode = luaL_check_string(L, 2); | 153 | const char *mode = luaL_check_string(L, 2); |
173 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 154 | luaL_check_type(L, 1, LUA_TTABLE); |
174 | if (*mode == '?') { | 155 | if (*mode == '?') { |
175 | char buff[3]; | 156 | char buff[3]; |
176 | char *s = buff; | 157 | char *s = buff; |
@@ -191,17 +172,11 @@ static int luaB_weakmode (lua_State *L) { | |||
191 | } | 172 | } |
192 | } | 173 | } |
193 | 174 | ||
194 | static int luaB_newtype (lua_State *L) { | ||
195 | const char *name = luaL_opt_string(L, 1, NULL); | ||
196 | lua_pushnumber(L, lua_newtype(L, name, LUA_TTABLE)); | ||
197 | return 1; | ||
198 | } | ||
199 | |||
200 | 175 | ||
201 | static int luaB_globals (lua_State *L) { | 176 | static int luaB_globals (lua_State *L) { |
202 | lua_getglobals(L); /* value to be returned */ | 177 | lua_getglobals(L); /* value to be returned */ |
203 | if (!lua_isnull(L, 1)) { | 178 | if (!lua_isnull(L, 1)) { |
204 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 179 | luaL_check_type(L, 1, LUA_TTABLE); |
205 | lua_pushvalue(L, 1); /* new table of globals */ | 180 | lua_pushvalue(L, 1); /* new table of globals */ |
206 | lua_setglobals(L); | 181 | lua_setglobals(L); |
207 | } | 182 | } |
@@ -209,43 +184,20 @@ static int luaB_globals (lua_State *L) { | |||
209 | } | 184 | } |
210 | 185 | ||
211 | static int luaB_rawget (lua_State *L) { | 186 | static int luaB_rawget (lua_State *L) { |
212 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 187 | luaL_check_type(L, 1, LUA_TTABLE); |
213 | luaL_check_any(L, 2); | 188 | luaL_check_any(L, 2); |
214 | lua_rawget(L, -2); | 189 | lua_rawget(L, -2); |
215 | return 1; | 190 | return 1; |
216 | } | 191 | } |
217 | 192 | ||
218 | static int luaB_rawset (lua_State *L) { | 193 | static int luaB_rawset (lua_State *L) { |
219 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 194 | luaL_check_type(L, 1, LUA_TTABLE); |
220 | luaL_check_any(L, 2); | 195 | luaL_check_any(L, 2); |
221 | luaL_check_any(L, 3); | 196 | luaL_check_any(L, 3); |
222 | lua_rawset(L, -3); | 197 | lua_rawset(L, -3); |
223 | return 1; | 198 | return 1; |
224 | } | 199 | } |
225 | 200 | ||
226 | static int luaB_settagmethod (lua_State *L) { | ||
227 | int tag = gettag(L, 1); | ||
228 | const char *event = luaL_check_string(L, 2); | ||
229 | luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, | ||
230 | "function or nil expected"); | ||
231 | if (strcmp(event, "gc") == 0) | ||
232 | lua_error(L, "cannot set `gc' tag method from Lua"); | ||
233 | lua_gettagmethod(L, tag, event); | ||
234 | lua_pushvalue(L, 3); | ||
235 | lua_settagmethod(L, tag, event); | ||
236 | return 1; | ||
237 | } | ||
238 | |||
239 | |||
240 | static int luaB_gettagmethod (lua_State *L) { | ||
241 | int tag = gettag(L, 1); | ||
242 | const char *event = luaL_check_string(L, 2); | ||
243 | if (strcmp(event, "gc") == 0) | ||
244 | lua_error(L, "cannot get `gc' tag method from Lua"); | ||
245 | lua_gettagmethod(L, tag, event); | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | 201 | ||
250 | static int luaB_gcinfo (lua_State *L) { | 202 | static int luaB_gcinfo (lua_State *L) { |
251 | lua_pushnumber(L, lua_getgccount(L)); | 203 | lua_pushnumber(L, lua_getgccount(L)); |
@@ -262,20 +214,20 @@ static int luaB_collectgarbage (lua_State *L) { | |||
262 | 214 | ||
263 | static int luaB_type (lua_State *L) { | 215 | static int luaB_type (lua_State *L) { |
264 | luaL_check_any(L, 1); | 216 | luaL_check_any(L, 1); |
265 | lua_pushstring(L, lua_type(L, 1)); | 217 | if (lua_isnull(L, 2)) |
266 | return 1; | 218 | lua_pushstring(L, lua_typename(L, lua_type(L, 1))); |
267 | } | 219 | else { |
268 | 220 | if (strcmp(lua_typename(L, lua_type(L, 1)), luaL_check_string(L, 2)) == 0) | |
269 | 221 | lua_pushnumber(L, 1); | |
270 | static int luaB_rawtype (lua_State *L) { | 222 | else |
271 | luaL_check_any(L, 1); | 223 | lua_pushnil(L); |
272 | lua_pushstring(L, lua_tag2name(L, lua_rawtag(L, 1))); | 224 | } |
273 | return 1; | 225 | return 1; |
274 | } | 226 | } |
275 | 227 | ||
276 | 228 | ||
277 | static int luaB_next (lua_State *L) { | 229 | static int luaB_next (lua_State *L) { |
278 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 230 | luaL_check_type(L, 1, LUA_TTABLE); |
279 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ | 231 | lua_settop(L, 2); /* create a 2nd argument if there isn't one */ |
280 | if (lua_next(L, 1)) | 232 | if (lua_next(L, 1)) |
281 | return 2; | 233 | return 2; |
@@ -393,7 +345,7 @@ static int luaB_require (lua_State *L) { | |||
393 | 345 | ||
394 | static int aux_unpack (lua_State *L, int arg) { | 346 | static int aux_unpack (lua_State *L, int arg) { |
395 | int n, i; | 347 | int n, i; |
396 | luaL_check_rawtype(L, arg, LUA_TTABLE); | 348 | luaL_check_type(L, arg, LUA_TTABLE); |
397 | n = lua_getn(L, arg); | 349 | n = lua_getn(L, arg); |
398 | luaL_check_stack(L, n, "table too big to unpack"); | 350 | luaL_check_stack(L, n, "table too big to unpack"); |
399 | for (i=1; i<=n; i++) /* push arg[1...n] */ | 351 | for (i=1; i<=n; i++) /* push arg[1...n] */ |
@@ -443,7 +395,7 @@ static int luaB_call (lua_State *L) { | |||
443 | 395 | ||
444 | static int luaB_tostring (lua_State *L) { | 396 | static int luaB_tostring (lua_State *L) { |
445 | char buff[64]; | 397 | char buff[64]; |
446 | switch (lua_rawtag(L, 1)) { | 398 | switch (lua_type(L, 1)) { |
447 | case LUA_TNUMBER: | 399 | case LUA_TNUMBER: |
448 | lua_pushstring(L, lua_tostring(L, 1)); | 400 | lua_pushstring(L, lua_tostring(L, 1)); |
449 | return 1; | 401 | return 1; |
@@ -451,16 +403,15 @@ static int luaB_tostring (lua_State *L) { | |||
451 | lua_pushvalue(L, 1); | 403 | lua_pushvalue(L, 1); |
452 | return 1; | 404 | return 1; |
453 | case LUA_TTABLE: | 405 | case LUA_TTABLE: |
454 | sprintf(buff, "%.40s: %p", lua_type(L, 1), lua_topointer(L, 1)); | 406 | sprintf(buff, "%.40s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1)); |
455 | break; | 407 | break; |
456 | case LUA_TFUNCTION: | 408 | case LUA_TFUNCTION: |
457 | sprintf(buff, "function: %p", lua_topointer(L, 1)); | 409 | sprintf(buff, "function: %p", lua_topointer(L, 1)); |
458 | break; | 410 | break; |
459 | case LUA_TUSERDATA: { | 411 | case LUA_TUSERDATA: { |
460 | const char *t = lua_type(L, 1); | 412 | const char *t = lua_typename(L, lua_type(L, 1)); |
461 | if (strcmp(t, "userdata") == 0) | 413 | if (strcmp(t, "userdata") == 0) |
462 | sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), | 414 | sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); |
463 | lua_touserdata(L, 1)); | ||
464 | else | 415 | else |
465 | sprintf(buff, "%.40s: %p", t, lua_touserdata(L, 1)); | 416 | sprintf(buff, "%.40s: %p", t, lua_touserdata(L, 1)); |
466 | break; | 417 | break; |
@@ -478,8 +429,8 @@ static int luaB_tostring (lua_State *L) { | |||
478 | 429 | ||
479 | static int luaB_foreachi (lua_State *L) { | 430 | static int luaB_foreachi (lua_State *L) { |
480 | int n, i; | 431 | int n, i; |
481 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 432 | luaL_check_type(L, 1, LUA_TTABLE); |
482 | luaL_check_rawtype(L, 2, LUA_TFUNCTION); | 433 | luaL_check_type(L, 2, LUA_TFUNCTION); |
483 | n = lua_getn(L, 1); | 434 | n = lua_getn(L, 1); |
484 | for (i=1; i<=n; i++) { | 435 | for (i=1; i<=n; i++) { |
485 | lua_pushvalue(L, 2); /* function */ | 436 | lua_pushvalue(L, 2); /* function */ |
@@ -495,8 +446,8 @@ static int luaB_foreachi (lua_State *L) { | |||
495 | 446 | ||
496 | 447 | ||
497 | static int luaB_foreach (lua_State *L) { | 448 | static int luaB_foreach (lua_State *L) { |
498 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 449 | luaL_check_type(L, 1, LUA_TTABLE); |
499 | luaL_check_rawtype(L, 2, LUA_TFUNCTION); | 450 | luaL_check_type(L, 2, LUA_TFUNCTION); |
500 | lua_pushnil(L); /* first index */ | 451 | lua_pushnil(L); /* first index */ |
501 | for (;;) { | 452 | for (;;) { |
502 | if (lua_next(L, 1) == 0) | 453 | if (lua_next(L, 1) == 0) |
@@ -523,7 +474,7 @@ static int luaB_assert (lua_State *L) { | |||
523 | 474 | ||
524 | 475 | ||
525 | static int luaB_getn (lua_State *L) { | 476 | static int luaB_getn (lua_State *L) { |
526 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 477 | luaL_check_type(L, 1, LUA_TTABLE); |
527 | lua_pushnumber(L, lua_getn(L, 1)); | 478 | lua_pushnumber(L, lua_getn(L, 1)); |
528 | return 1; | 479 | return 1; |
529 | } | 480 | } |
@@ -532,7 +483,7 @@ static int luaB_getn (lua_State *L) { | |||
532 | static int luaB_tinsert (lua_State *L) { | 483 | static int luaB_tinsert (lua_State *L) { |
533 | int v = lua_gettop(L); /* number of arguments */ | 484 | int v = lua_gettop(L); /* number of arguments */ |
534 | int n, pos; | 485 | int n, pos; |
535 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 486 | luaL_check_type(L, 1, LUA_TTABLE); |
536 | n = lua_getn(L, 1); | 487 | n = lua_getn(L, 1); |
537 | if (v == 2) /* called with only 2 arguments */ | 488 | if (v == 2) /* called with only 2 arguments */ |
538 | pos = n+1; | 489 | pos = n+1; |
@@ -553,7 +504,7 @@ static int luaB_tinsert (lua_State *L) { | |||
553 | 504 | ||
554 | static int luaB_tremove (lua_State *L) { | 505 | static int luaB_tremove (lua_State *L) { |
555 | int pos, n; | 506 | int pos, n; |
556 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 507 | luaL_check_type(L, 1, LUA_TTABLE); |
557 | n = lua_getn(L, 1); | 508 | n = lua_getn(L, 1); |
558 | pos = luaL_opt_int(L, 2, n); | 509 | pos = luaL_opt_int(L, 2, n); |
559 | if (n <= 0) return 0; /* table is `empty' */ | 510 | if (n <= 0) return 0; /* table is `empty' */ |
@@ -665,10 +616,10 @@ static void auxsort (lua_State *L, int l, int u) { | |||
665 | 616 | ||
666 | static int luaB_sort (lua_State *L) { | 617 | static int luaB_sort (lua_State *L) { |
667 | int n; | 618 | int n; |
668 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 619 | luaL_check_type(L, 1, LUA_TTABLE); |
669 | n = lua_getn(L, 1); | 620 | n = lua_getn(L, 1); |
670 | if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ | 621 | if (!lua_isnull(L, 2)) /* is there a 2nd argument? */ |
671 | luaL_check_rawtype(L, 2, LUA_TFUNCTION); | 622 | luaL_check_type(L, 2, LUA_TFUNCTION); |
672 | lua_settop(L, 2); /* make sure there is two arguments */ | 623 | lua_settop(L, 2); /* make sure there is two arguments */ |
673 | auxsort(L, 1, n); | 624 | auxsort(L, 1, n); |
674 | return 0; | 625 | return 0; |
@@ -686,28 +637,19 @@ static const luaL_reg base_funcs[] = { | |||
686 | {"dofile", luaB_dofile}, | 637 | {"dofile", luaB_dofile}, |
687 | {"dostring", luaB_dostring}, | 638 | {"dostring", luaB_dostring}, |
688 | {"error", luaB_error}, | 639 | {"error", luaB_error}, |
640 | {"eventtable", luaB_eventtable}, | ||
689 | {"foreach", luaB_foreach}, | 641 | {"foreach", luaB_foreach}, |
690 | {"foreachi", luaB_foreachi}, | 642 | {"foreachi", luaB_foreachi}, |
691 | {"gcinfo", luaB_gcinfo}, | 643 | {"gcinfo", luaB_gcinfo}, |
692 | {"getglobal", luaB_getglobal}, | 644 | {"getglobal", luaB_getglobal}, /* compatibility with 4.0 */ |
693 | {"gettagmethod", luaB_gettagmethod}, | ||
694 | {"globals", luaB_globals}, | 645 | {"globals", luaB_globals}, |
695 | {"loadfile", luaB_loadfile}, | 646 | {"loadfile", luaB_loadfile}, |
696 | {"loadstring", luaB_loadstring}, | 647 | {"loadstring", luaB_loadstring}, |
697 | {"newtype", luaB_newtype}, | ||
698 | {"newtag", luaB_newtype}, /* for compatibility 4.0 */ | ||
699 | {"next", luaB_next}, | 648 | {"next", luaB_next}, |
700 | {"print", luaB_print}, | 649 | {"print", luaB_print}, |
701 | {"rawget", luaB_rawget}, | 650 | {"rawget", luaB_rawget}, |
702 | {"rawset", luaB_rawset}, | 651 | {"rawset", luaB_rawset}, |
703 | {"rawgettable", luaB_rawget}, /* for compatibility 3.2 */ | 652 | {"setglobal", luaB_setglobal}, /* compatibility with 4.0 */ |
704 | {"rawsettable", luaB_rawset}, /* for compatibility 3.2 */ | ||
705 | {"rawtype", luaB_rawtype}, | ||
706 | {"setglobal", luaB_setglobal}, | ||
707 | {"settag", luaB_settype}, /* for compatibility 4.0 */ | ||
708 | {"settype", luaB_settype}, | ||
709 | {"settagmethod", luaB_settagmethod}, | ||
710 | {"tag", luaB_tag}, | ||
711 | {"tonumber", luaB_tonumber}, | 653 | {"tonumber", luaB_tonumber}, |
712 | {"tostring", luaB_tostring}, | 654 | {"tostring", luaB_tostring}, |
713 | {"type", luaB_type}, | 655 | {"type", luaB_type}, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.92 2001/10/31 19:58:11 roberto Exp $ | 2 | ** $Id: ldebug.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -205,22 +205,8 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { | |||
205 | } | 205 | } |
206 | 206 | ||
207 | 207 | ||
208 | static const char *travtagmethods (global_State *G, const TObject *o) { | ||
209 | if (ttype(o) == LUA_TFUNCTION) { | ||
210 | int e; | ||
211 | for (e=0; e<TM_N; e++) { | ||
212 | int t; | ||
213 | for (t=0; t<G->ntag; t++) | ||
214 | if (clvalue(o) == luaT_gettm(G, t, e)) | ||
215 | return luaT_eventname[e]; | ||
216 | } | ||
217 | } | ||
218 | return NULL; | ||
219 | } | ||
220 | |||
221 | |||
222 | static const char *travglobals (lua_State *L, const TObject *o) { | 208 | static const char *travglobals (lua_State *L, const TObject *o) { |
223 | Table *g = hvalue(&L->gt); | 209 | Table *g = hvalue(gt(L)); |
224 | int i = sizenode(g); | 210 | int i = sizenode(g); |
225 | while (i--) { | 211 | while (i--) { |
226 | Node *n = node(g, i); | 212 | Node *n = node(g, i); |
@@ -235,10 +221,7 @@ static void getname (lua_State *L, const TObject *f, lua_Debug *ar) { | |||
235 | /* try to find a name for given function */ | 221 | /* try to find a name for given function */ |
236 | if ((ar->name = travglobals(L, f)) != NULL) | 222 | if ((ar->name = travglobals(L, f)) != NULL) |
237 | ar->namewhat = "global"; | 223 | ar->namewhat = "global"; |
238 | /* not found: try tag methods */ | 224 | else ar->namewhat = ""; /* not found */ |
239 | else if ((ar->name = travtagmethods(G(L), f)) != NULL) | ||
240 | ar->namewhat = "tag-method"; | ||
241 | else ar->namewhat = ""; /* not found at all */ | ||
242 | } | 225 | } |
243 | 226 | ||
244 | 227 | ||
@@ -531,7 +514,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, | |||
531 | void luaG_typeerror (lua_State *L, StkId o, const char *op) { | 514 | void luaG_typeerror (lua_State *L, StkId o, const char *op) { |
532 | const char *name; | 515 | const char *name; |
533 | const char *kind = getobjname(L, o, &name); | 516 | const char *kind = getobjname(L, o, &name); |
534 | const char *t = luaT_typename(G(L), o); | 517 | const char *t = luaT_typenames[ttype(o)]; |
535 | if (kind) | 518 | if (kind) |
536 | luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", | 519 | luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", |
537 | op, kind, name, t); | 520 | op, kind, name, t); |
@@ -556,8 +539,8 @@ void luaG_aritherror (lua_State *L, StkId p1, TObject *p2) { | |||
556 | 539 | ||
557 | 540 | ||
558 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { | 541 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { |
559 | const char *t1 = luaT_typename(G(L), p1); | 542 | const char *t1 = luaT_typenames[ttype(p1)]; |
560 | const char *t2 = luaT_typename(G(L), p2); | 543 | const char *t2 = luaT_typenames[ttype(p2)]; |
561 | if (t1[2] == t2[2]) | 544 | if (t1[2] == t2[2]) |
562 | luaO_verror(L, "attempt to compare two %.10s values", t1); | 545 | luaO_verror(L, "attempt to compare two %.10s values", t1); |
563 | else | 546 | else |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.144 2001/11/27 20:56:47 roberto Exp $ | 2 | ** $Id: ldo.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
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 | */ |
@@ -43,8 +43,7 @@ void luaD_init (lua_State *L, int stacksize) { | |||
43 | stacksize += EXTRA_STACK; | 43 | stacksize += EXTRA_STACK; |
44 | L->stack = luaM_newvector(L, stacksize, TObject); | 44 | L->stack = luaM_newvector(L, stacksize, TObject); |
45 | L->stacksize = stacksize; | 45 | L->stacksize = stacksize; |
46 | setnilvalue(L->stack); /* the `initial' function */ | 46 | L->top = L->basefunc.base = L->stack + RESERVED_STACK_PREFIX; |
47 | L->top = L->basefunc.base = L->stack + 1; | ||
48 | restore_stack_limit(L); | 47 | restore_stack_limit(L); |
49 | } | 48 | } |
50 | 49 | ||
@@ -143,12 +142,13 @@ void luaD_call (lua_State *L, StkId func) { | |||
143 | CallInfo ci; | 142 | CallInfo ci; |
144 | if (ttype(func) != LUA_TFUNCTION) { | 143 | if (ttype(func) != LUA_TFUNCTION) { |
145 | /* `func' is not a function; check the `function' tag method */ | 144 | /* `func' is not a function; check the `function' tag method */ |
146 | Closure *tm = luaT_gettmbyObj(G(L), func, TM_FUNCTION); | 145 | const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); |
147 | if (tm == NULL) | 146 | if (tm == NULL || ttype(tm) != LUA_TFUNCTION) |
148 | luaG_typeerror(L, func, "call"); | 147 | luaG_typeerror(L, func, "call"); |
149 | luaD_openstack(L, func); | 148 | luaD_openstack(L, func); |
150 | setclvalue(func, tm); /* tag method is the new function to be called */ | 149 | setobj(func, tm); /* tag method is the new function to be called */ |
151 | } | 150 | } |
151 | lua_assert(ttype(func) == LUA_TFUNCTION); | ||
152 | ci.prev = L->ci; /* chain new callinfo */ | 152 | ci.prev = L->ci; /* chain new callinfo */ |
153 | L->ci = &ci; | 153 | L->ci = &ci; |
154 | ci.base = func+1; | 154 | ci.base = func+1; |
@@ -300,9 +300,12 @@ struct lua_longjmp { | |||
300 | 300 | ||
301 | 301 | ||
302 | static void message (lua_State *L, const char *s) { | 302 | static void message (lua_State *L, const char *s) { |
303 | StkId top = L->top; | 303 | TObject o, m; |
304 | luaV_getglobal(L, luaS_newliteral(L, LUA_ERRORMESSAGE), top); | 304 | setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); |
305 | if (ttype(top) == LUA_TFUNCTION) { | 305 | luaV_gettable(L, gt(L), &o, &m); |
306 | if (ttype(&m) == LUA_TFUNCTION) { | ||
307 | StkId top = L->top; | ||
308 | setobj(top, &m); | ||
306 | incr_top; | 309 | incr_top; |
307 | setsvalue(top+1, luaS_new(L, s)); | 310 | setsvalue(top+1, luaS_new(L, s)); |
308 | incr_top; | 311 | incr_top; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 1.49 2001/11/06 21:41:53 roberto Exp $ | 2 | ** $Id: lfunc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -54,7 +54,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
54 | } | 54 | } |
55 | p = luaM_new(L, UpVal); /* not found: create a new one */ | 55 | p = luaM_new(L, UpVal); /* not found: create a new one */ |
56 | p->v = level; /* current value lives in the stack */ | 56 | p->v = level; /* current value lives in the stack */ |
57 | p->mark = 1; /* won't participate in GC while open */ | ||
58 | p->next = *pp; /* chain it in the proper position */ | 57 | p->next = *pp; /* chain it in the proper position */ |
59 | *pp = p; | 58 | *pp = p; |
60 | return p; | 59 | return p; |
@@ -68,7 +67,6 @@ void luaF_close (lua_State *L, StkId level) { | |||
68 | p->v = &p->value; /* now current value lives here */ | 67 | p->v = &p->value; /* now current value lives here */ |
69 | L->openupval = p->next; /* remove from `open' list */ | 68 | L->openupval = p->next; /* remove from `open' list */ |
70 | p->next = G(L)->rootupval; /* chain in `closed' list */ | 69 | p->next = G(L)->rootupval; /* chain in `closed' list */ |
71 | p->mark = 0; /* now it can be collected */ | ||
72 | G(L)->rootupval = p; | 70 | G(L)->rootupval = p; |
73 | } | 71 | } |
74 | } | 72 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.116 2001/11/06 21:41:53 roberto Exp $ | 2 | ** $Id: lgc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -30,6 +30,15 @@ typedef struct GCState { | |||
30 | #define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} | 30 | #define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} |
31 | 31 | ||
32 | 32 | ||
33 | /* mark tricks for userdata */ | ||
34 | #define isudmarked(u) (u->uv.len & 1) | ||
35 | #define markud(u) (u->uv.len |= 1) | ||
36 | #define unmarkud(u) (u->uv.len--) | ||
37 | |||
38 | |||
39 | /* mark tricks for upvalues (assume that open upvalues are always marked) */ | ||
40 | #define isupvalmarked(uv) ((uv)->v != &(uv)->value) | ||
41 | |||
33 | 42 | ||
34 | static void markobject (GCState *st, TObject *o); | 43 | static void markobject (GCState *st, TObject *o); |
35 | 44 | ||
@@ -66,9 +75,9 @@ static void markclosure (GCState *st, Closure *cl) { | |||
66 | protomark(cl->l.p); | 75 | protomark(cl->l.p); |
67 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ | 76 | for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ |
68 | UpVal *u = cl->l.upvals[i]; | 77 | UpVal *u = cl->l.upvals[i]; |
69 | if (!u->mark) { | 78 | if (!isupvalmarked(u)) { |
70 | u->mark = 1; | 79 | markobject(st, &u->value); |
71 | markobject(st, u->v); | 80 | u->v = NULL; /* mark it! */ |
72 | } | 81 | } |
73 | } | 82 | } |
74 | } | 83 | } |
@@ -90,8 +99,8 @@ static void markobject (GCState *st, TObject *o) { | |||
90 | strmark(tsvalue(o)); | 99 | strmark(tsvalue(o)); |
91 | break; | 100 | break; |
92 | case LUA_TUSERDATA: | 101 | case LUA_TUSERDATA: |
93 | if (!ismarkedudata(uvalue(o))) | 102 | if (!isudmarked(uvalue(o))) |
94 | switchudatamark(uvalue(o)); | 103 | markud(uvalue(o)); |
95 | break; | 104 | break; |
96 | case LUA_TFUNCTION: | 105 | case LUA_TFUNCTION: |
97 | markclosure(st, clvalue(o)); | 106 | markclosure(st, clvalue(o)); |
@@ -112,7 +121,6 @@ static void markstacks (lua_State *L, GCState *st) { | |||
112 | lua_State *L1 = L; | 121 | lua_State *L1 = L; |
113 | do { /* for each thread */ | 122 | do { /* for each thread */ |
114 | StkId o, lim; | 123 | StkId o, lim; |
115 | markobject(st, &L1->gt); /* mark table of globals */ | ||
116 | for (o=L1->stack; o<L1->top; o++) | 124 | for (o=L1->stack; o<L1->top; o++) |
117 | markobject(st, o); | 125 | markobject(st, o); |
118 | lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK | 126 | lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK |
@@ -124,17 +132,10 @@ static void markstacks (lua_State *L, GCState *st) { | |||
124 | } | 132 | } |
125 | 133 | ||
126 | 134 | ||
127 | static void marktagmethods (global_State *G, GCState *st) { | 135 | static void markudet (lua_State *L, GCState *st) { |
128 | int t; | 136 | Udata *u; |
129 | for (t=0; t<G->ntag; t++) { | 137 | for (u = G(L)->rootudata; u; u = u->uv.next) |
130 | struct TM *tm = &G->TMtable[t]; | 138 | marktable(st, u->uv.eventtable); |
131 | int e; | ||
132 | if (tm->name) strmark(tm->name); | ||
133 | for (e=0; e<TM_N; e++) { | ||
134 | Closure *cl = tm->method[e]; | ||
135 | if (cl) markclosure(st, cl); | ||
136 | } | ||
137 | } | ||
138 | } | 139 | } |
139 | 140 | ||
140 | 141 | ||
@@ -152,6 +153,7 @@ static void traversetable (GCState *st, Table *h) { | |||
152 | h->mark = st->toclear; /* put in the appropriate list */ | 153 | h->mark = st->toclear; /* put in the appropriate list */ |
153 | st->toclear = h; | 154 | st->toclear = h; |
154 | } | 155 | } |
156 | marktable(st, h->eventtable); | ||
155 | if (!(mode & LUA_WEAK_VALUE)) { | 157 | if (!(mode & LUA_WEAK_VALUE)) { |
156 | i = sizearray(h); | 158 | i = sizearray(h); |
157 | while (i--) | 159 | while (i--) |
@@ -172,11 +174,9 @@ static void traversetable (GCState *st, Table *h) { | |||
172 | 174 | ||
173 | 175 | ||
174 | static void markall (lua_State *L, GCState *st) { | 176 | static void markall (lua_State *L, GCState *st) { |
175 | marktagmethods(G(L), st); /* mark tag methods */ | ||
176 | markstacks(L, st); /* mark all stacks */ | 177 | markstacks(L, st); /* mark all stacks */ |
177 | marktable(st, G(L)->type2tag); | 178 | markudet(L, st); /* mark userdata's event tables */ |
178 | markobject(st, &G(L)->registry); | 179 | while (st->tmark) { /* traverse marked tables */ |
179 | while (st->tmark) { /* mark tables */ | ||
180 | Table *h = st->tmark; /* get first table from list */ | 180 | Table *h = st->tmark; /* get first table from list */ |
181 | st->tmark = h->mark; /* remove it from list */ | 181 | st->tmark = h->mark; /* remove it from list */ |
182 | traversetable(st, h); | 182 | traversetable(st, h); |
@@ -189,7 +189,7 @@ static int hasmark (const TObject *o) { | |||
189 | case LUA_TSTRING: | 189 | case LUA_TSTRING: |
190 | return tsvalue(o)->tsv.marked; | 190 | return tsvalue(o)->tsv.marked; |
191 | case LUA_TUSERDATA: | 191 | case LUA_TUSERDATA: |
192 | return ismarkedudata(uvalue(o)); | 192 | return isudmarked(uvalue(o)); |
193 | case LUA_TTABLE: | 193 | case LUA_TTABLE: |
194 | return ismarked(hvalue(o)); | 194 | return ismarked(hvalue(o)); |
195 | case LUA_TFUNCTION: | 195 | case LUA_TFUNCTION: |
@@ -261,8 +261,9 @@ static void collectupval (lua_State *L) { | |||
261 | UpVal **v = &G(L)->rootupval; | 261 | UpVal **v = &G(L)->rootupval; |
262 | UpVal *curr; | 262 | UpVal *curr; |
263 | while ((curr = *v) != NULL) { | 263 | while ((curr = *v) != NULL) { |
264 | if (curr->mark) { | 264 | if (isupvalmarked(curr)) { |
265 | curr->mark = 0; | 265 | lua_assert(curr->v == NULL); |
266 | curr->v = &curr->value; /* unmark */ | ||
266 | v = &curr->next; /* next */ | 267 | v = &curr->next; /* next */ |
267 | } | 268 | } |
268 | else { | 269 | else { |
@@ -289,26 +290,27 @@ static void collecttable (lua_State *L) { | |||
289 | } | 290 | } |
290 | 291 | ||
291 | 292 | ||
292 | static void collectudata (lua_State *L, int keep) { | 293 | static Udata *collectudata (lua_State *L, int keep) { |
293 | Udata **p = &G(L)->rootudata; | 294 | Udata **p = &G(L)->rootudata; |
294 | Udata *curr; | 295 | Udata *curr; |
296 | Udata *collected = NULL; | ||
295 | while ((curr = *p) != NULL) { | 297 | while ((curr = *p) != NULL) { |
296 | if (ismarkedudata(curr)) { | 298 | if (isudmarked(curr)) { |
297 | switchudatamark(curr); /* unmark */ | 299 | unmarkud(curr); |
298 | p = &curr->uv.next; | 300 | p = &curr->uv.next; |
299 | } | 301 | } |
300 | else { /* collect */ | 302 | else { /* collect */ |
301 | int tag = curr->uv.tag; | 303 | const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC); |
302 | *p = curr->uv.next; | 304 | *p = curr->uv.next; |
303 | if (keep || /* must keep all of them (to close state)? */ | 305 | if (keep || tm != NULL) { |
304 | luaT_gettm(G(L), tag, TM_GC)) { /* or is there a GC tag method? */ | 306 | curr->uv.next = collected; |
305 | curr->uv.next = G(L)->TMtable[tag].collected; /* chain udata ... */ | 307 | collected = curr; |
306 | G(L)->TMtable[tag].collected = curr; /* ... to call its TM later */ | ||
307 | } | 308 | } |
308 | else /* no tag method; delete udata */ | 309 | else /* no gc action; delete udata */ |
309 | luaM_free(L, curr, sizeudata(curr->uv.len)); | 310 | luaM_free(L, curr, sizeudata(curr->uv.len)); |
310 | } | 311 | } |
311 | } | 312 | } |
313 | return collected; | ||
312 | } | 314 | } |
313 | 315 | ||
314 | 316 | ||
@@ -347,14 +349,14 @@ static void checkMbuffer (lua_State *L) { | |||
347 | } | 349 | } |
348 | 350 | ||
349 | 351 | ||
350 | static void callgcTM (lua_State *L, const TObject *obj) { | 352 | static void callgcTM (lua_State *L, Udata *udata) { |
351 | Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC); | 353 | const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC); |
352 | if (tm != NULL) { | 354 | if (tm != NULL && ttype(tm) == LUA_TFUNCTION) { |
353 | int oldah = L->allowhooks; | 355 | int oldah = L->allowhooks; |
354 | StkId top = L->top; | 356 | StkId top = L->top; |
355 | L->allowhooks = 0; /* stop debug hooks during GC tag methods */ | 357 | L->allowhooks = 0; /* stop debug hooks during GC tag methods */ |
356 | setclvalue(top, tm); | 358 | setobj(top, tm); |
357 | setobj(top+1, obj); | 359 | setuvalue(top+1, udata); |
358 | L->top += 2; | 360 | L->top += 2; |
359 | luaD_call(L, top); | 361 | luaD_call(L, top); |
360 | L->top = top; /* restore top */ | 362 | L->top = top; /* restore top */ |
@@ -363,53 +365,52 @@ static void callgcTM (lua_State *L, const TObject *obj) { | |||
363 | } | 365 | } |
364 | 366 | ||
365 | 367 | ||
366 | static void callgcTMudata (lua_State *L) { | 368 | static void callgcTMudata (lua_State *L, Udata *c) { |
367 | int tag; | ||
368 | luaD_checkstack(L, 3); | 369 | luaD_checkstack(L, 3); |
369 | for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */ | 370 | L->top++; /* reserve space to keep udata while runs its gc method */ |
370 | Udata *udata; | 371 | while (c != NULL) { |
371 | while ((udata = G(L)->TMtable[tag].collected) != NULL) { | 372 | Udata *udata = c; |
372 | G(L)->TMtable[tag].collected = udata->uv.next; /* remove it from list */ | 373 | c = udata->uv.next; /* remove udata from list */ |
373 | udata->uv.next = G(L)->rootudata; /* resurect it */ | 374 | udata->uv.next = G(L)->rootudata; /* resurect it */ |
374 | G(L)->rootudata = udata; | 375 | G(L)->rootudata = udata; |
375 | setuvalue(L->top, udata); | 376 | setuvalue(L->top - 1, udata); |
376 | L->top++; /* keep it in stack to avoid being (recursively) collected */ | 377 | callgcTM(L, udata); |
377 | callgcTM(L, L->top-1); | 378 | /* mark udata as finalized (default event table) */ |
378 | uvalue(L->top-1)->uv.tag = 0; /* default tag (udata is `finalized') */ | 379 | uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L)); |
379 | L->top--; | ||
380 | } | ||
381 | } | 380 | } |
381 | L->top--; | ||
382 | } | 382 | } |
383 | 383 | ||
384 | 384 | ||
385 | void luaC_callallgcTM (lua_State *L) { | 385 | void luaC_callallgcTM (lua_State *L) { |
386 | if (G(L)->rootudata) { /* avoid problems with incomplete states */ | 386 | if (G(L)->rootudata) { /* avoid problems with incomplete states */ |
387 | collectudata(L, 1); /* collect all udata into tag lists */ | 387 | Udata *c = collectudata(L, 1); /* collect all udata */ |
388 | callgcTMudata(L); /* call their GC tag methods */ | 388 | callgcTMudata(L, c); /* call their GC tag methods */ |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | 392 | ||
393 | void luaC_collect (lua_State *L, int all) { | 393 | Udata *luaC_collect (lua_State *L, int all) { |
394 | collectudata(L, 0); | 394 | Udata *c = collectudata(L, 0); |
395 | collectstrings(L, all); | 395 | collectstrings(L, all); |
396 | collecttable(L); | 396 | collecttable(L); |
397 | collectproto(L); | 397 | collectproto(L); |
398 | collectupval(L); | 398 | collectupval(L); |
399 | collectclosures(L); | 399 | collectclosures(L); |
400 | return c; | ||
400 | } | 401 | } |
401 | 402 | ||
402 | 403 | ||
403 | void luaC_collectgarbage (lua_State *L) { | 404 | void luaC_collectgarbage (lua_State *L) { |
405 | Udata *c; | ||
404 | GCState st; | 406 | GCState st; |
405 | st.tmark = NULL; | 407 | st.tmark = NULL; |
406 | st.toclear = NULL; | 408 | st.toclear = NULL; |
407 | markall(L, &st); | 409 | markall(L, &st); |
408 | cleartables(st.toclear); | 410 | cleartables(st.toclear); |
409 | luaC_collect(L, 0); | 411 | c = luaC_collect(L, 0); |
410 | checkMbuffer(L); | 412 | checkMbuffer(L); |
411 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | 413 | G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ |
412 | callgcTMudata(L); | 414 | callgcTMudata(L, c); |
413 | callgcTM(L, &luaO_nilobject); | ||
414 | } | 415 | } |
415 | 416 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 1.11 2001/06/12 18:43:13 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | 17 | ||
18 | void luaC_callallgcTM (lua_State *L); | 18 | void luaC_callallgcTM (lua_State *L); |
19 | void luaC_collect (lua_State *L, int all); | 19 | Udata *luaC_collect (lua_State *L, int all); |
20 | void luaC_collectgarbage (lua_State *L); | 20 | void luaC_collectgarbage (lua_State *L); |
21 | 21 | ||
22 | 22 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 1.124 2001/10/26 17:33:30 roberto Exp $ | 2 | ** $Id: liolib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -61,6 +61,7 @@ static int pushresult (lua_State *L, int i) { | |||
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
64 | |||
64 | /* | 65 | /* |
65 | ** {====================================================== | 66 | ** {====================================================== |
66 | ** FILE Operations | 67 | ** FILE Operations |
@@ -68,14 +69,30 @@ static int pushresult (lua_State *L, int i) { | |||
68 | */ | 69 | */ |
69 | 70 | ||
70 | 71 | ||
71 | #define checkfile(L,f) (strcmp(lua_type(L,(f)), FILEHANDLE) == 0) | 72 | |
73 | static int checkfile (lua_State *L, int findex, const char *tname) { | ||
74 | int res; | ||
75 | lua_geteventtable(L, findex); | ||
76 | lua_pushstring(L, tname); | ||
77 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
78 | res = lua_equal(L, -1, -2); | ||
79 | lua_pop(L, 2); | ||
80 | return res; | ||
81 | } | ||
82 | |||
83 | |||
84 | /* temporary?? should be in auxlib... */ | ||
85 | static void *luaL_check_userdata (lua_State *L, int findex, const char *tn) { | ||
86 | luaL_arg_check(L, checkfile(L, findex, tn), findex, "bad file"); | ||
87 | return lua_touserdata(L, findex); | ||
88 | } | ||
72 | 89 | ||
73 | 90 | ||
74 | static FILE *getopthandle (lua_State *L, int inout) { | 91 | static FILE *getopthandle (lua_State *L, int inout) { |
75 | FILE *p = (FILE *)(lua_touserdata(L, 1)); | 92 | FILE *p = (FILE *)(lua_touserdata(L, 1)); |
76 | if (p != NULL) { /* is it a userdata ? */ | 93 | if (p != NULL) { /* is it a userdata ? */ |
77 | if (!checkfile(L, 1)) { /* not a valid file handle? */ | 94 | if (!checkfile(L, 1, FILEHANDLE)) { /* not a valid file handle? */ |
78 | if (strcmp(lua_type(L, 1), CLOSEDFILEHANDLE) == 0) | 95 | if (checkfile(L, 1, CLOSEDFILEHANDLE)) |
79 | luaL_argerror(L, 1, "file is closed"); | 96 | luaL_argerror(L, 1, "file is closed"); |
80 | else | 97 | else |
81 | luaL_argerror(L, 1, "(invalid value)"); | 98 | luaL_argerror(L, 1, "(invalid value)"); |
@@ -84,7 +101,7 @@ static FILE *getopthandle (lua_State *L, int inout) { | |||
84 | } | 101 | } |
85 | else { /* try global value */ | 102 | else { /* try global value */ |
86 | lua_getglobal(L, filenames[inout]); | 103 | lua_getglobal(L, filenames[inout]); |
87 | if (!checkfile(L,-1)) | 104 | if (!checkfile(L, -1, FILEHANDLE)) |
88 | luaL_verror(L, "global variable `%.10s' is not a valid file handle", | 105 | luaL_verror(L, "global variable `%.10s' is not a valid file handle", |
89 | filenames[inout]); | 106 | filenames[inout]); |
90 | p = (FILE *)(lua_touserdata(L, -1)); | 107 | p = (FILE *)(lua_touserdata(L, -1)); |
@@ -95,7 +112,9 @@ static FILE *getopthandle (lua_State *L, int inout) { | |||
95 | 112 | ||
96 | static void newfile (lua_State *L, FILE *f) { | 113 | static void newfile (lua_State *L, FILE *f) { |
97 | lua_newuserdatabox(L, f); | 114 | lua_newuserdatabox(L, f); |
98 | lua_settag(L, lua_name2tag(L, FILEHANDLE)); | 115 | lua_pushliteral(L, FILEHANDLE); |
116 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
117 | lua_seteventtable(L, -2); | ||
99 | } | 118 | } |
100 | 119 | ||
101 | 120 | ||
@@ -130,7 +149,9 @@ static int io_close (lua_State *L) { | |||
130 | int status = 1; | 149 | int status = 1; |
131 | if (f != stdin && f != stdout && f != stderr) { | 150 | if (f != stdin && f != stdout && f != stderr) { |
132 | lua_settop(L, 1); /* make sure file is on top */ | 151 | lua_settop(L, 1); /* make sure file is on top */ |
133 | lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE)); | 152 | lua_pushliteral(L, CLOSEDFILEHANDLE); |
153 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
154 | lua_seteventtable(L, 1); | ||
134 | status = (CLOSEFILE(L, f) == 0); | 155 | status = (CLOSEFILE(L, f) == 0); |
135 | } | 156 | } |
136 | return pushresult(L, status); | 157 | return pushresult(L, status); |
@@ -301,7 +322,7 @@ static int io_read (lua_State *L) { | |||
301 | luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments"); | 322 | luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments"); |
302 | success = 1; | 323 | success = 1; |
303 | for (n = 1; n<=nargs && success; n++) { | 324 | for (n = 1; n<=nargs && success; n++) { |
304 | if (lua_rawtag(L, n) == LUA_TNUMBER) { | 325 | if (lua_type(L, n) == LUA_TNUMBER) { |
305 | size_t l = (size_t)lua_tonumber(L, n); | 326 | size_t l = (size_t)lua_tonumber(L, n); |
306 | success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); | 327 | success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); |
307 | } | 328 | } |
@@ -353,7 +374,7 @@ static int io_write (lua_State *L) { | |||
353 | int arg; | 374 | int arg; |
354 | int status = 1; | 375 | int status = 1; |
355 | for (arg=1; arg<=nargs; arg++) { | 376 | for (arg=1; arg<=nargs; arg++) { |
356 | if (lua_rawtag(L, arg) == LUA_TNUMBER) { | 377 | if (lua_type(L, arg) == LUA_TNUMBER) { |
357 | /* optimization: could be done exactly as for strings */ | 378 | /* optimization: could be done exactly as for strings */ |
358 | status = status && | 379 | status = status && |
359 | fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | 380 | fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
@@ -514,7 +535,7 @@ static int io_time (lua_State *L) { | |||
514 | else { | 535 | else { |
515 | time_t t; | 536 | time_t t; |
516 | struct tm ts; | 537 | struct tm ts; |
517 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 538 | luaL_check_type(L, 1, LUA_TTABLE); |
518 | lua_settop(L, 1); /* make sure table is at the top */ | 539 | lua_settop(L, 1); /* make sure table is at the top */ |
519 | ts.tm_sec = getfield(L, "sec", 0); | 540 | ts.tm_sec = getfield(L, "sec", 0); |
520 | ts.tm_min = getfield(L, "min", 0); | 541 | ts.tm_min = getfield(L, "min", 0); |
@@ -677,8 +698,18 @@ static const luaL_reg iolib[] = { | |||
677 | 698 | ||
678 | 699 | ||
679 | LUALIB_API int lua_iolibopen (lua_State *L) { | 700 | LUALIB_API int lua_iolibopen (lua_State *L) { |
680 | int iotag = lua_newtype(L, FILEHANDLE, LUA_TUSERDATA); | 701 | lua_pushliteral(L, FILEHANDLE); |
681 | lua_newtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA); | 702 | lua_newtable(L); /* event table for FILEHANDLE */ |
703 | /* close files when collected */ | ||
704 | lua_pushliteral(L, "gc"); | ||
705 | lua_pushcfunction(L, file_collect); | ||
706 | lua_settable(L, -3); | ||
707 | /* put new eventtable into registry */ | ||
708 | lua_settable(L, LUA_REGISTRYINDEX); /* registry.FILEHANDLE = eventtable */ | ||
709 | lua_pushliteral(L, CLOSEDFILEHANDLE); | ||
710 | /* event table for CLOSEDFILEHANDLE */ | ||
711 | lua_newtable(L); | ||
712 | lua_settable(L, LUA_REGISTRYINDEX); | ||
682 | luaL_openl(L, iolib); | 713 | luaL_openl(L, iolib); |
683 | /* predefined file handles */ | 714 | /* predefined file handles */ |
684 | newfilewithname(L, stdin, basicfiles[INFILE]); | 715 | newfilewithname(L, stdin, basicfiles[INFILE]); |
@@ -686,9 +717,6 @@ LUALIB_API int lua_iolibopen (lua_State *L) { | |||
686 | newfilewithname(L, stderr, "_STDERR"); | 717 | newfilewithname(L, stderr, "_STDERR"); |
687 | resetfile(L, INFILE); | 718 | resetfile(L, INFILE); |
688 | resetfile(L, OUTFILE); | 719 | resetfile(L, OUTFILE); |
689 | /* close files when collected */ | ||
690 | lua_pushcfunction(L, file_collect); | ||
691 | lua_settagmethod(L, iotag, "gc"); | ||
692 | return 0; | 720 | return 0; |
693 | } | 721 | } |
694 | 722 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lmathlib.c,v 1.38 2001/03/26 14:31:49 roberto Exp $ | 2 | ** $Id: lmathlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Standard mathematical library | 3 | ** Standard mathematical library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -220,6 +220,7 @@ static const luaL_reg mathlib[] = { | |||
220 | {"log10", math_log10}, | 220 | {"log10", math_log10}, |
221 | {"exp", math_exp}, | 221 | {"exp", math_exp}, |
222 | {"deg", math_deg}, | 222 | {"deg", math_deg}, |
223 | {"pow", math_pow}, | ||
223 | {"rad", math_rad}, | 224 | {"rad", math_rad}, |
224 | {"random", math_random}, | 225 | {"random", math_random}, |
225 | {"randomseed", math_randomseed} | 226 | {"randomseed", math_randomseed} |
@@ -230,8 +231,6 @@ static const luaL_reg mathlib[] = { | |||
230 | */ | 231 | */ |
231 | LUALIB_API int lua_mathlibopen (lua_State *L) { | 232 | LUALIB_API int lua_mathlibopen (lua_State *L) { |
232 | luaL_openl(L, mathlib); | 233 | luaL_openl(L, mathlib); |
233 | lua_pushcfunction(L, math_pow); | ||
234 | lua_settagmethod(L, LUA_TNUMBER, "pow"); | ||
235 | lua_pushnumber(L, PI); | 234 | lua_pushnumber(L, PI); |
236 | lua_setglobal(L, "PI"); | 235 | lua_setglobal(L, "PI"); |
237 | return 0; | 236 | return 0; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.116 2001/11/06 21:41:53 roberto Exp $ | 2 | ** $Id: lobject.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -31,15 +31,6 @@ | |||
31 | #define NUM_TAGS 6 | 31 | #define NUM_TAGS 6 |
32 | 32 | ||
33 | 33 | ||
34 | /* | ||
35 | ** extra tags: | ||
36 | ** first is used locally when moving an upvalue from the stack to the heap; | ||
37 | ** second prefixes upvalues in the heap | ||
38 | */ | ||
39 | #define LUA_TUPVAL 6 | ||
40 | #define LUA_HEAPUPVAL 7 | ||
41 | |||
42 | |||
43 | typedef union { | 34 | typedef union { |
44 | union TString *ts; | 35 | union TString *ts; |
45 | union Udata *u; | 36 | union Udata *u; |
@@ -122,17 +113,14 @@ typedef union TString { | |||
122 | typedef union Udata { | 113 | typedef union Udata { |
123 | union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ | 114 | union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ |
124 | struct { | 115 | struct { |
125 | int tag; /* negative means `marked' (only during GC) */ | 116 | struct Table *eventtable; |
126 | void *value; | 117 | void *value; |
127 | size_t len; | 118 | size_t len; /* least bit reserved for gc mark */ |
128 | union Udata *next; /* chain for list of all udata */ | 119 | union Udata *next; /* chain for list of all udata */ |
129 | } uv; | 120 | } uv; |
130 | } Udata; | 121 | } Udata; |
131 | 122 | ||
132 | 123 | ||
133 | #define switchudatamark(u) ((u)->uv.tag = (-((u)->uv.tag+1))) | ||
134 | #define ismarkedudata(u) ((u)->uv.tag < 0) | ||
135 | |||
136 | 124 | ||
137 | 125 | ||
138 | /* | 126 | /* |
@@ -175,7 +163,6 @@ typedef struct LocVar { | |||
175 | 163 | ||
176 | typedef struct UpVal { | 164 | typedef struct UpVal { |
177 | TObject *v; /* points to stack or to its own value */ | 165 | TObject *v; /* points to stack or to its own value */ |
178 | int mark; | ||
179 | struct UpVal *next; | 166 | struct UpVal *next; |
180 | TObject value; /* the value (when closed) */ | 167 | TObject value; /* the value (when closed) */ |
181 | } UpVal; | 168 | } UpVal; |
@@ -227,12 +214,13 @@ typedef struct Node { | |||
227 | 214 | ||
228 | 215 | ||
229 | typedef struct Table { | 216 | typedef struct Table { |
217 | struct Table *eventtable; | ||
230 | TObject *array; /* array part */ | 218 | TObject *array; /* array part */ |
231 | Node *node; | 219 | Node *node; |
232 | int htag; | ||
233 | int sizearray; /* size of `array' array */ | 220 | int sizearray; /* size of `array' array */ |
234 | lu_byte lsizenode; /* log2 of size of `node' array */ | 221 | lu_byte lsizenode; /* log2 of size of `node' array */ |
235 | lu_byte weakmode; | 222 | lu_byte weakmode; |
223 | unsigned short flags; /* 1<<p means tagmethod(p) is not present */ | ||
236 | Node *firstfree; /* this position is free; all positions after it are full */ | 224 | Node *firstfree; /* this position is free; all positions after it are full */ |
237 | struct Table *next; | 225 | struct Table *next; |
238 | struct Table *mark; /* marked tables (point to itself when not marked) */ | 226 | struct Table *mark; /* marked tables (point to itself when not marked) */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.72 2001/11/06 21:40:51 roberto Exp $ | 2 | ** $Id: lstate.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -40,12 +40,14 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
40 | so->stacksize += LUA_MINSTACK; | 40 | so->stacksize += LUA_MINSTACK; |
41 | if (so->L != NULL) { /* shared global state? */ | 41 | if (so->L != NULL) { /* shared global state? */ |
42 | L->_G = G(so->L); | 42 | L->_G = G(so->L); |
43 | L->gt = so->L->gt; /* share table of globals */ | ||
44 | so->L->next->previous = L; /* insert L into linked list */ | 43 | so->L->next->previous = L; /* insert L into linked list */ |
45 | L->next = so->L->next; | 44 | L->next = so->L->next; |
46 | so->L->next = L; | 45 | so->L->next = L; |
47 | L->previous = so->L; | 46 | L->previous = so->L; |
48 | luaD_init(L, so->stacksize); /* init stack */ | 47 | luaD_init(L, so->stacksize); /* init stack */ |
48 | setobj(defaultet(L), defaultet(so->L)); /* share default event table */ | ||
49 | setobj(gt(L), gt(so->L)); /* share table of globals */ | ||
50 | setobj(registry(L), registry(so->L)); /* share registry */ | ||
49 | } | 51 | } |
50 | else { /* create a new global state */ | 52 | else { /* create a new global state */ |
51 | L->_G = luaM_new(L, global_State); | 53 | L->_G = luaM_new(L, global_State); |
@@ -59,17 +61,17 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
59 | G(L)->roottable = NULL; | 61 | G(L)->roottable = NULL; |
60 | G(L)->rootudata = NULL; | 62 | G(L)->rootudata = NULL; |
61 | G(L)->rootupval = NULL; | 63 | G(L)->rootupval = NULL; |
62 | G(L)->TMtable = NULL; | ||
63 | G(L)->sizeTM = 0; | ||
64 | G(L)->ntag = 0; | ||
65 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); | 64 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); |
66 | luaD_init(L, so->stacksize); /* init stack */ | 65 | luaD_init(L, so->stacksize); /* init stack */ |
67 | sethvalue(&L->gt, luaH_new(L, 0, 4)); /* table of globals */ | 66 | /* create default event table with a dummy table, and then close the loop */ |
68 | G(L)->type2tag = luaH_new(L, 0, 3); | 67 | sethvalue(defaultet(L), NULL); |
69 | sethvalue(&G(L)->registry, luaH_new(L, 0, 0)); | 68 | sethvalue(defaultet(L), luaH_new(L, 0, 4)); |
69 | hvalue(defaultet(L))->eventtable = hvalue(defaultet(L)); | ||
70 | sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ | ||
71 | sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */ | ||
70 | luaS_resize(L, 4); /* initial size of string table */ | 72 | luaS_resize(L, 4); /* initial size of string table */ |
71 | luaX_init(L); | ||
72 | luaT_init(L); | 73 | luaT_init(L); |
74 | luaX_init(L); | ||
73 | G(L)->GCthreshold = 4*G(L)->nblocks; | 75 | G(L)->GCthreshold = 4*G(L)->nblocks; |
74 | } | 76 | } |
75 | } | 77 | } |
@@ -122,7 +124,6 @@ static void close_state (lua_State *L, lua_State *OL) { | |||
122 | lua_assert(G(L)->rootupval == NULL); | 124 | lua_assert(G(L)->rootupval == NULL); |
123 | lua_assert(G(L)->roottable == NULL); | 125 | lua_assert(G(L)->roottable == NULL); |
124 | luaS_freeall(L); | 126 | luaS_freeall(L); |
125 | luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); | ||
126 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); | 127 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); |
127 | luaM_freelem(NULL, L->_G); | 128 | luaM_freelem(NULL, L->_G); |
128 | } | 129 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 1.64 2001/11/06 21:40:51 roberto Exp $ | 2 | ** $Id: lstate.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -7,8 +7,10 @@ | |||
7 | #ifndef lstate_h | 7 | #ifndef lstate_h |
8 | #define lstate_h | 8 | #define lstate_h |
9 | 9 | ||
10 | #include "lobject.h" | ||
11 | #include "lua.h" | 10 | #include "lua.h" |
11 | |||
12 | #include "lobject.h" | ||
13 | #include "ltm.h" | ||
12 | #include "luadebug.h" | 14 | #include "luadebug.h" |
13 | 15 | ||
14 | 16 | ||
@@ -40,7 +42,24 @@ | |||
40 | 42 | ||
41 | 43 | ||
42 | struct lua_longjmp; /* defined in ldo.c */ | 44 | struct lua_longjmp; /* defined in ldo.c */ |
43 | struct TM; /* defined in ltm.h */ | 45 | |
46 | |||
47 | |||
48 | /* | ||
49 | ** reserve init of stack to store some global values | ||
50 | */ | ||
51 | |||
52 | /* default event table (both for tables and udata) */ | ||
53 | #define defaultet(L) (L->stack) | ||
54 | |||
55 | /* table of globals */ | ||
56 | #define gt(L) (L->stack + 1) | ||
57 | |||
58 | /* registry */ | ||
59 | #define registry(L) (L->stack + 2) | ||
60 | |||
61 | #define RESERVED_STACK_PREFIX 3 | ||
62 | |||
44 | 63 | ||
45 | 64 | ||
46 | typedef struct stringtable { | 65 | typedef struct stringtable { |
@@ -57,11 +76,6 @@ typedef struct global_State { | |||
57 | void *Mbuffer; /* global buffer */ | 76 | void *Mbuffer; /* global buffer */ |
58 | size_t Mbuffsize; /* size of Mbuffer */ | 77 | size_t Mbuffsize; /* size of Mbuffer */ |
59 | stringtable strt; /* hash table for strings */ | 78 | stringtable strt; /* hash table for strings */ |
60 | Table *type2tag; /* hash table from type names to tags */ | ||
61 | TObject registry; /* registry table */ | ||
62 | struct TM *TMtable; /* table for tag methods */ | ||
63 | int sizeTM; /* size of TMtable */ | ||
64 | int ntag; /* number of tags in TMtable */ | ||
65 | lu_mem GCthreshold; | 79 | lu_mem GCthreshold; |
66 | lu_mem nblocks; /* number of `bytes' currently allocated */ | 80 | lu_mem nblocks; /* number of `bytes' currently allocated */ |
67 | Proto *rootproto; /* list of all prototypes */ | 81 | Proto *rootproto; /* list of all prototypes */ |
@@ -69,6 +83,7 @@ typedef struct global_State { | |||
69 | Table *roottable; /* list of all tables */ | 83 | Table *roottable; /* list of all tables */ |
70 | Udata *rootudata; /* list of all userdata */ | 84 | Udata *rootudata; /* list of all userdata */ |
71 | UpVal *rootupval; /* list of closed up values */ | 85 | UpVal *rootupval; /* list of closed up values */ |
86 | TString *tmname[TM_N]; /* array with tag-method names */ | ||
72 | } global_State; | 87 | } global_State; |
73 | 88 | ||
74 | 89 | ||
@@ -80,10 +95,9 @@ struct lua_State { | |||
80 | StkId top; /* first free slot in the stack */ | 95 | StkId top; /* first free slot in the stack */ |
81 | CallInfo *ci; /* call info for current function */ | 96 | CallInfo *ci; /* call info for current function */ |
82 | StkId stack_last; /* last free slot in the stack */ | 97 | StkId stack_last; /* last free slot in the stack */ |
83 | TObject gt; /* table for globals */ | ||
84 | global_State *_G; | ||
85 | StkId stack; /* stack base */ | 98 | StkId stack; /* stack base */ |
86 | int stacksize; | 99 | int stacksize; |
100 | global_State *_G; | ||
87 | lua_Hook callhook; | 101 | lua_Hook callhook; |
88 | lua_Hook linehook; | 102 | lua_Hook linehook; |
89 | int allowhooks; | 103 | int allowhooks; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.67 2001/08/31 19:46:07 roberto Exp $ | 2 | ** $Id: lstring.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -84,9 +84,11 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
84 | 84 | ||
85 | 85 | ||
86 | Udata *luaS_newudata (lua_State *L, size_t s) { | 86 | Udata *luaS_newudata (lua_State *L, size_t s) { |
87 | Udata *u = cast(Udata *, luaM_malloc(L, sizeudata(s))); | 87 | Udata *u; |
88 | if (s & 1) s++; /* make sure size is even */ | ||
89 | u = cast(Udata *, luaM_malloc(L, sizeudata(s))); | ||
88 | u->uv.len = s; | 90 | u->uv.len = s; |
89 | u->uv.tag = 0; | 91 | u->uv.eventtable = hvalue(defaultet(L)); |
90 | u->uv.value = u + 1; | 92 | u->uv.value = u + 1; |
91 | /* chain it on udata list */ | 93 | /* chain it on udata list */ |
92 | u->uv.next = G(L)->rootudata; | 94 | u->uv.next = G(L)->rootudata; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.73 2001/10/26 17:33:30 roberto Exp $ | 2 | ** $Id: lstrlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -97,7 +97,7 @@ static int str_concat (lua_State *L) { | |||
97 | size_t lsep; | 97 | size_t lsep; |
98 | const char *sep = luaL_opt_lstr(L, 2, "", &lsep); | 98 | const char *sep = luaL_opt_lstr(L, 2, "", &lsep); |
99 | int n, i; | 99 | int n, i; |
100 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 100 | luaL_check_type(L, 1, LUA_TTABLE); |
101 | luaL_buffinit(L, &b); | 101 | luaL_buffinit(L, &b); |
102 | n = lua_getn(L, 1); | 102 | n = lua_getn(L, 1); |
103 | for (i=1; i<=n; i++) { | 103 | for (i=1; i<=n; i++) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 1.88 2001/11/16 16:29:51 roberto Exp $ | 2 | ** $Id: ltable.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -258,11 +258,12 @@ static void rehash (lua_State *L, Table *t) { | |||
258 | 258 | ||
259 | Table *luaH_new (lua_State *L, int narray, int lnhash) { | 259 | Table *luaH_new (lua_State *L, int narray, int lnhash) { |
260 | Table *t = luaM_new(L, Table); | 260 | Table *t = luaM_new(L, Table); |
261 | t->htag = TagDefault; | 261 | t->eventtable = hvalue(defaultet(L)); |
262 | t->next = G(L)->roottable; | 262 | t->next = G(L)->roottable; |
263 | G(L)->roottable = t; | 263 | G(L)->roottable = t; |
264 | t->mark = t; | 264 | t->mark = t; |
265 | t->weakmode = 0; | 265 | t->weakmode = 0; |
266 | t->flags = ~0; | ||
266 | /* temporary values (kept only if some malloc fails) */ | 267 | /* temporary values (kept only if some malloc fails) */ |
267 | t->array = NULL; | 268 | t->array = NULL; |
268 | t->sizearray = 0; | 269 | t->sizearray = 0; |
@@ -419,19 +420,7 @@ void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val) { | |||
419 | if (ttype(key) == LUA_TNIL) luaD_error(L, "table index is nil"); | 420 | if (ttype(key) == LUA_TNIL) luaD_error(L, "table index is nil"); |
420 | newkey(L, t, key, val); | 421 | newkey(L, t, key, val); |
421 | } | 422 | } |
422 | } | 423 | t->flags = 0; |
423 | |||
424 | |||
425 | void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val) { | ||
426 | const TObject *p = luaH_getstr(t, key); | ||
427 | if (p != &luaO_nilobject) { | ||
428 | settableval(p, val); | ||
429 | } | ||
430 | else { | ||
431 | TObject k; | ||
432 | setsvalue(&k, key); | ||
433 | newkey(L, t, &k, val); | ||
434 | } | ||
435 | } | 424 | } |
436 | 425 | ||
437 | 426 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.h,v 1.37 2001/10/25 19:14:14 roberto Exp $ | 2 | ** $Id: ltable.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,7 +20,6 @@ | |||
20 | const TObject *luaH_getnum (Table *t, int key); | 20 | const TObject *luaH_getnum (Table *t, int key); |
21 | void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val); | 21 | void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val); |
22 | const TObject *luaH_getstr (Table *t, TString *key); | 22 | const TObject *luaH_getstr (Table *t, TString *key); |
23 | void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val); | ||
24 | const TObject *luaH_get (Table *t, const TObject *key); | 23 | const TObject *luaH_get (Table *t, const TObject *key); |
25 | void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val); | 24 | void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val); |
26 | Table *luaH_new (lua_State *L, int narray, int lnhash); | 25 | Table *luaH_new (lua_State *L, int narray, int lnhash); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 1.96 2001/11/06 21:41:43 roberto Exp $ | 2 | ** $Id: ltests.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
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 | */ |
@@ -240,13 +240,13 @@ static int mem_query (lua_State *L) { | |||
240 | 240 | ||
241 | static int hash_query (lua_State *L) { | 241 | static int hash_query (lua_State *L) { |
242 | if (lua_isnull(L, 2)) { | 242 | if (lua_isnull(L, 2)) { |
243 | luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected"); | 243 | luaL_arg_check(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); |
244 | lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash); | 244 | lua_pushnumber(L, tsvalue(luaA_index(L, 1))->tsv.hash); |
245 | } | 245 | } |
246 | else { | 246 | else { |
247 | TObject *o = luaA_index(L, 1); | 247 | TObject *o = luaA_index(L, 1); |
248 | Table *t; | 248 | Table *t; |
249 | luaL_check_rawtype(L, 2, LUA_TTABLE); | 249 | luaL_check_type(L, 2, LUA_TTABLE); |
250 | t = hvalue(luaA_index(L, 2)); | 250 | t = hvalue(luaA_index(L, 2)); |
251 | lua_pushnumber(L, luaH_mainposition(t, o) - t->node); | 251 | lua_pushnumber(L, luaH_mainposition(t, o) - t->node); |
252 | } | 252 | } |
@@ -257,7 +257,7 @@ static int hash_query (lua_State *L) { | |||
257 | static int table_query (lua_State *L) { | 257 | static int table_query (lua_State *L) { |
258 | const Table *t; | 258 | const Table *t; |
259 | int i = luaL_opt_int(L, 2, -1); | 259 | int i = luaL_opt_int(L, 2, -1); |
260 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 260 | luaL_check_type(L, 1, LUA_TTABLE); |
261 | t = hvalue(luaA_index(L, 1)); | 261 | t = hvalue(luaA_index(L, 1)); |
262 | if (i == -1) { | 262 | if (i == -1) { |
263 | lua_pushnumber(L, t->sizearray); | 263 | lua_pushnumber(L, t->sizearray); |
@@ -333,6 +333,18 @@ static int unref (lua_State *L) { | |||
333 | return 0; | 333 | return 0; |
334 | } | 334 | } |
335 | 335 | ||
336 | static int eventtable (lua_State *L) { | ||
337 | luaL_check_any(L, 1); | ||
338 | if (lua_isnull(L, 2)) | ||
339 | lua_geteventtable(L, 1); | ||
340 | else { | ||
341 | lua_settop(L, 2); | ||
342 | luaL_check_type(L, 2, LUA_TTABLE); | ||
343 | lua_seteventtable(L, 1); | ||
344 | } | ||
345 | return 1; | ||
346 | } | ||
347 | |||
336 | static int newuserdata (lua_State *L) { | 348 | static int newuserdata (lua_State *L) { |
337 | size_t size = luaL_check_int(L, 1); | 349 | size_t size = luaL_check_int(L, 1); |
338 | char *p = cast(char *, lua_newuserdata(L, size)); | 350 | char *p = cast(char *, lua_newuserdata(L, size)); |
@@ -345,24 +357,13 @@ static int newuserdatabox (lua_State *L) { | |||
345 | return 1; | 357 | return 1; |
346 | } | 358 | } |
347 | 359 | ||
348 | static int settag (lua_State *L) { | ||
349 | luaL_check_any(L, 1); | ||
350 | lua_pushvalue(L, 1); /* push value */ | ||
351 | lua_settag(L, luaL_check_int(L, 2)); | ||
352 | return 1; /* return value */ | ||
353 | } | ||
354 | 360 | ||
355 | static int udataval (lua_State *L) { | 361 | static int udataval (lua_State *L) { |
356 | luaL_check_rawtype(L, 1, LUA_TUSERDATA); | 362 | luaL_check_type(L, 1, LUA_TUSERDATA); |
357 | lua_pushnumber(L, cast(int, lua_touserdata(L, 1))); | 363 | lua_pushnumber(L, cast(int, lua_touserdata(L, 1))); |
358 | return 1; | 364 | return 1; |
359 | } | 365 | } |
360 | 366 | ||
361 | static int newtag (lua_State *L) { | ||
362 | lua_pushnumber(L, lua_newtype(L, lua_tostring(L, 1), | ||
363 | cast(int, lua_tonumber(L, 2)))); | ||
364 | return 1; | ||
365 | } | ||
366 | 367 | ||
367 | static int doonnewstack (lua_State *L) { | 368 | static int doonnewstack (lua_State *L) { |
368 | lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1)); | 369 | lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1)); |
@@ -435,16 +436,6 @@ static int doremote (lua_State *L) { | |||
435 | } | 436 | } |
436 | } | 437 | } |
437 | 438 | ||
438 | static int settagmethod (lua_State *L) { | ||
439 | int tag = luaL_check_int(L, 1); | ||
440 | const char *event = luaL_check_string(L, 2); | ||
441 | luaL_check_any(L, 3); | ||
442 | lua_gettagmethod(L, tag, event); | ||
443 | lua_pushvalue(L, 3); | ||
444 | lua_settagmethod(L, tag, event); | ||
445 | return 1; | ||
446 | } | ||
447 | |||
448 | 439 | ||
449 | static int log2_aux (lua_State *L) { | 440 | static int log2_aux (lua_State *L) { |
450 | lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1))); | 441 | lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1))); |
@@ -614,18 +605,14 @@ static int testC (lua_State *L) { | |||
614 | else if EQ("dostring") { | 605 | else if EQ("dostring") { |
615 | lua_dostring(L, luaL_check_string(L, getnum)); | 606 | lua_dostring(L, luaL_check_string(L, getnum)); |
616 | } | 607 | } |
617 | else if EQ("settagmethod") { | 608 | else if EQ("seteventtable") { |
618 | int tag = getnum; | 609 | lua_seteventtable(L, getnum); |
619 | const char *event = getname; | ||
620 | lua_settagmethod(L, tag, event); | ||
621 | } | 610 | } |
622 | else if EQ("gettagmethod") { | 611 | else if EQ("geteventtable") { |
623 | int tag = getnum; | 612 | lua_geteventtable(L, getnum); |
624 | const char *event = getname; | ||
625 | lua_gettagmethod(L, tag, event); | ||
626 | } | 613 | } |
627 | else if EQ("type") { | 614 | else if EQ("type") { |
628 | lua_pushstring(L, lua_type(L, getnum)); | 615 | lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); |
629 | } | 616 | } |
630 | else luaL_verror(L, "unknown instruction %.30s", buff); | 617 | else luaL_verror(L, "unknown instruction %.30s", buff); |
631 | } | 618 | } |
@@ -651,16 +638,14 @@ static const struct luaL_reg tests_funcs[] = { | |||
651 | {"unref", unref}, | 638 | {"unref", unref}, |
652 | {"d2s", d2s}, | 639 | {"d2s", d2s}, |
653 | {"s2d", s2d}, | 640 | {"s2d", s2d}, |
641 | {"eventtable", eventtable}, | ||
654 | {"newuserdata", newuserdata}, | 642 | {"newuserdata", newuserdata}, |
655 | {"newuserdatabox", newuserdatabox}, | 643 | {"newuserdatabox", newuserdatabox}, |
656 | {"settag", settag}, | ||
657 | {"udataval", udataval}, | 644 | {"udataval", udataval}, |
658 | {"newtag", newtag}, | ||
659 | {"doonnewstack", doonnewstack}, | 645 | {"doonnewstack", doonnewstack}, |
660 | {"newstate", newstate}, | 646 | {"newstate", newstate}, |
661 | {"closestate", closestate}, | 647 | {"closestate", closestate}, |
662 | {"doremote", doremote}, | 648 | {"doremote", doremote}, |
663 | {"settagmethod", settagmethod}, | ||
664 | {"log2", log2_aux}, | 649 | {"log2", log2_aux}, |
665 | {"totalmem", mem_query} | 650 | {"totalmem", mem_query} |
666 | }; | 651 | }; |
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 1.28 2001/10/02 16:43:54 roberto Exp $ | 2 | ** $Id: ltm.h,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 | */ |
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | 10 | ||
11 | #include "lobject.h" | 11 | #include "lobject.h" |
12 | #include "lstate.h" | ||
13 | 12 | ||
14 | /* | 13 | /* |
15 | * WARNING: if you change the order of this enumeration, | 14 | * WARNING: if you change the order of this enumeration, |
@@ -19,8 +18,7 @@ typedef enum { | |||
19 | TM_GETTABLE = 0, | 18 | TM_GETTABLE = 0, |
20 | TM_SETTABLE, | 19 | TM_SETTABLE, |
21 | TM_INDEX, | 20 | TM_INDEX, |
22 | TM_GETGLOBAL, | 21 | TM_GC, |
23 | TM_SETGLOBAL, | ||
24 | TM_ADD, | 22 | TM_ADD, |
25 | TM_SUB, | 23 | TM_SUB, |
26 | TM_MUL, | 24 | TM_MUL, |
@@ -29,51 +27,20 @@ typedef enum { | |||
29 | TM_UNM, | 27 | TM_UNM, |
30 | TM_LT, | 28 | TM_LT, |
31 | TM_CONCAT, | 29 | TM_CONCAT, |
32 | TM_GC, | 30 | TM_CALL, |
33 | TM_FUNCTION, | ||
34 | TM_N /* number of elements in the enum */ | 31 | TM_N /* number of elements in the enum */ |
35 | } TMS; | 32 | } TMS; |
36 | 33 | ||
37 | 34 | ||
38 | 35 | ||
39 | /* | 36 | #define fasttm(l,et,e) \ |
40 | ** masks for allowable tag methods | 37 | (((et)->flags & (1<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e])) |
41 | ** (see `luaT_validevents') | ||
42 | */ | ||
43 | #define HAS_TM_GETGLOBAL(L,t) ((1<<(t)) & ((1<<LUA_TUSERDATA) | \ | ||
44 | (1<<LUA_TTABLE) | \ | ||
45 | (1<<LUA_TNIL))) | ||
46 | |||
47 | #define HAS_TM_SETGLOBAL(L,t) ((1<<(t)) & ((1<<LUA_TUSERDATA) | \ | ||
48 | (1<<LUA_TTABLE) | \ | ||
49 | (1<<LUA_TNIL) | \ | ||
50 | (1<<LUA_TFUNCTION))) | ||
51 | |||
52 | |||
53 | |||
54 | struct TM { | ||
55 | Closure *method[TM_N]; | ||
56 | Udata *collected; /* list of garbage-collected udata with this tag */ | ||
57 | TString *name; /* type name */ | ||
58 | int basictype; | ||
59 | }; | ||
60 | |||
61 | |||
62 | #define luaT_gettm(G,tag,event) (G->TMtable[tag].method[event]) | ||
63 | #define luaT_gettmbyObj(G,o,e) (luaT_gettm((G),luaT_tag(o),(e))) | ||
64 | |||
65 | #define typenamebytag(G, t) getstr(G->TMtable[t].name) | ||
66 | |||
67 | |||
68 | #define validtag(G,t) (NUM_TAGS <= (t) && (t) < G->ntag) | ||
69 | |||
70 | extern const char *const luaT_eventname[]; | ||
71 | 38 | ||
72 | 39 | ||
40 | const TObject *luaT_gettm (Table *events, TMS event, TString *ename); | ||
41 | const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event); | ||
73 | void luaT_init (lua_State *L); | 42 | void luaT_init (lua_State *L); |
74 | int luaT_newtag (lua_State *L, const char *name, int basictype); | ||
75 | const char *luaT_typename (global_State *G, const TObject *o); | ||
76 | int luaT_tag (const TObject *o); | ||
77 | 43 | ||
44 | extern const char *const luaT_typenames[]; | ||
78 | 45 | ||
79 | #endif | 46 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.107 2001/10/31 19:58:11 roberto Exp $ | 2 | ** $Id: lua.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - An Extensible Extension Language |
4 | ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil | 4 | ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil |
5 | ** e-mail: info@lua.org | 5 | ** e-mail: info@lua.org |
@@ -55,15 +55,11 @@ typedef struct lua_State lua_State; | |||
55 | typedef int (*lua_CFunction) (lua_State *L); | 55 | typedef int (*lua_CFunction) (lua_State *L); |
56 | 56 | ||
57 | 57 | ||
58 | /* | ||
59 | ** an invalid `tag' | ||
60 | */ | ||
61 | #define LUA_NOTAG (-1) | ||
62 | 58 | ||
63 | /* | 59 | /* |
64 | ** tags for basic types | 60 | ** basic types |
65 | */ | 61 | */ |
66 | #define LUA_TNONE LUA_NOTAG | 62 | #define LUA_TNONE (-1) |
67 | 63 | ||
68 | #define LUA_TUSERDATA 0 | 64 | #define LUA_TUSERDATA 0 |
69 | #define LUA_TNIL 1 | 65 | #define LUA_TNIL 1 |
@@ -120,12 +116,11 @@ LUA_API int lua_stackspace (lua_State *L); | |||
120 | ** access functions (stack -> C) | 116 | ** access functions (stack -> C) |
121 | */ | 117 | */ |
122 | 118 | ||
123 | LUA_API const char *lua_type (lua_State *L, int index); | ||
124 | LUA_API int lua_isnumber (lua_State *L, int index); | 119 | LUA_API int lua_isnumber (lua_State *L, int index); |
125 | LUA_API int lua_isstring (lua_State *L, int index); | 120 | LUA_API int lua_isstring (lua_State *L, int index); |
126 | LUA_API int lua_iscfunction (lua_State *L, int index); | 121 | LUA_API int lua_iscfunction (lua_State *L, int index); |
127 | LUA_API int lua_tag (lua_State *L, int index); | 122 | LUA_API int lua_type (lua_State *L, int index); |
128 | LUA_API int lua_rawtag (lua_State *L, int index); | 123 | LUA_API const char *lua_typename (lua_State *L, int type); |
129 | 124 | ||
130 | LUA_API int lua_equal (lua_State *L, int index1, int index2); | 125 | LUA_API int lua_equal (lua_State *L, int index1, int index2); |
131 | LUA_API int lua_lessthan (lua_State *L, int index1, int index2); | 126 | LUA_API int lua_lessthan (lua_State *L, int index1, int index2); |
@@ -155,9 +150,9 @@ LUA_API void lua_getglobal (lua_State *L, const char *name); | |||
155 | LUA_API void lua_gettable (lua_State *L, int index); | 150 | LUA_API void lua_gettable (lua_State *L, int index); |
156 | LUA_API void lua_rawget (lua_State *L, int index); | 151 | LUA_API void lua_rawget (lua_State *L, int index); |
157 | LUA_API void lua_rawgeti (lua_State *L, int index, int n); | 152 | LUA_API void lua_rawgeti (lua_State *L, int index, int n); |
158 | LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); | ||
159 | LUA_API void lua_newtable (lua_State *L); | 153 | LUA_API void lua_newtable (lua_State *L); |
160 | LUA_API void lua_getweakregistry (lua_State *L); | 154 | LUA_API void lua_getweakregistry (lua_State *L); |
155 | LUA_API void lua_geteventtable (lua_State *L, int objindex); | ||
161 | 156 | ||
162 | 157 | ||
163 | /* | 158 | /* |
@@ -168,7 +163,7 @@ LUA_API void lua_settable (lua_State *L, int index); | |||
168 | LUA_API void lua_rawset (lua_State *L, int index); | 163 | LUA_API void lua_rawset (lua_State *L, int index); |
169 | LUA_API void lua_rawseti (lua_State *L, int index, int n); | 164 | LUA_API void lua_rawseti (lua_State *L, int index, int n); |
170 | LUA_API void lua_setglobals (lua_State *L); | 165 | LUA_API void lua_setglobals (lua_State *L); |
171 | LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); | 166 | LUA_API void lua_seteventtable (lua_State *L, int objindex); |
172 | 167 | ||
173 | 168 | ||
174 | /* | 169 | /* |
@@ -194,11 +189,6 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); | |||
194 | /* | 189 | /* |
195 | ** miscellaneous functions | 190 | ** miscellaneous functions |
196 | */ | 191 | */ |
197 | LUA_API int lua_newtype (lua_State *L, const char *name, int basictype); | ||
198 | LUA_API void lua_settag (lua_State *L, int tag); | ||
199 | |||
200 | LUA_API int lua_name2tag (lua_State *L, const char *name); | ||
201 | LUA_API const char *lua_tag2name (lua_State *L, int tag); | ||
202 | 192 | ||
203 | LUA_API void lua_error (lua_State *L, const char *s); | 193 | LUA_API void lua_error (lua_State *L, const char *s); |
204 | 194 | ||
@@ -228,11 +218,11 @@ LUA_API int lua_getweakmode (lua_State *L, int index); | |||
228 | #define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) | 218 | #define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) |
229 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) | 219 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) |
230 | 220 | ||
231 | #define lua_isfunction(L,n) (lua_rawtag(L,n) == LUA_TFUNCTION) | 221 | #define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) |
232 | #define lua_istable(L,n) (lua_rawtag(L,n) == LUA_TTABLE) | 222 | #define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) |
233 | #define lua_isuserdata(L,n) (lua_rawtag(L,n) == LUA_TUSERDATA) | 223 | #define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) |
234 | #define lua_isnil(L,n) (lua_rawtag(L,n) == LUA_TNIL) | 224 | #define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) |
235 | #define lua_isnull(L,n) (lua_rawtag(L,n) == LUA_TNONE) | 225 | #define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) |
236 | 226 | ||
237 | #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, \ | 227 | #define lua_pushliteral(L, s) lua_pushlstring(L, "" s, \ |
238 | (sizeof(s)/sizeof(char))-1) | 228 | (sizeof(s)/sizeof(char))-1) |
@@ -245,8 +235,6 @@ LUA_API int lua_getweakmode (lua_State *L, int index); | |||
245 | /* | 235 | /* |
246 | ** compatibility macros and functions | 236 | ** compatibility macros and functions |
247 | */ | 237 | */ |
248 | #define lua_newtag(L) lua_newtype(L, NULL, LUA_TNONE) | ||
249 | #define lua_typename lua_tag2name | ||
250 | 238 | ||
251 | LUA_API void lua_pushupvalues (lua_State *L); | 239 | LUA_API void lua_pushupvalues (lua_State *L); |
252 | 240 | ||
@@ -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: { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 1.31 2001/09/07 17:39:10 roberto Exp $ | 2 | ** $Id: lvm.h,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 | */ |
@@ -20,8 +20,6 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n); | |||
20 | int luaV_tostring (lua_State *L, TObject *obj); | 20 | int luaV_tostring (lua_State *L, TObject *obj); |
21 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); | 21 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); |
22 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); | 22 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); |
23 | void luaV_getglobal (lua_State *L, TString *s, StkId res); | ||
24 | void luaV_setglobal (lua_State *L, TString *s, StkId val); | ||
25 | StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base); | 23 | StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base); |
26 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); | 24 | int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); |
27 | void luaV_strconc (lua_State *L, int total, StkId top); | 25 | void luaV_strconc (lua_State *L, int total, StkId top); |