commit 25dc9b7fafe608c428a0950986ea8a1cb4dd7fa9
parent 78c507b7b83a85c106b619ce2050725a80627a25
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Tue, 25 Jun 2002 16:19:11 -0300
new functions `dofile' and `pairs'; correct way to check proxies
Diffstat:
M | lbaselib.c | | | 72 | ++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 file changed, 50 insertions(+), 22 deletions(-)
diff --git a/lbaselib.c b/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.83 2002/06/20 20:41:46 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.84 2002/06/24 17:23:16 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -34,7 +34,7 @@ static int luaB_print (lua_State *L) {
const char *s;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
- lua_upcall(L, 1, 1);
+ lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */
if (s == NULL)
return luaL_error(L, "`tostring' must return a string to `print'");
@@ -83,8 +83,10 @@ static int luaB_error (lua_State *L) {
static int luaB_getmetatable (lua_State *L) {
luaL_check_any(L, 1);
- if (!lua_getmetatable(L, 1))
- return 0; /* no metatable */
+ if (!lua_getmetatable(L, 1)) {
+ lua_pushnil(L);
+ return 1; /* no metatable */
+ }
else {
lua_pushliteral(L, "__metatable");
lua_rawget(L, -2);
@@ -182,11 +184,20 @@ static int luaB_next (lua_State *L) {
}
-static int luaB_nexti (lua_State *L) {
+static int luaB_pairs (lua_State *L) {
+ luaL_check_type(L, 1, LUA_TTABLE);
+ lua_getglobal(L, "next"); /* return generator, */
+ lua_pushvalue(L, 1); /* state, */
+ lua_pushnil(L); /* and initial value */
+ return 3;
+}
+
+
+static int luaB_ipairs (lua_State *L) {
lua_Number i = lua_tonumber(L, 2);
luaL_check_type(L, 1, LUA_TTABLE);
if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */
- lua_getglobal(L, "nexti"); /* return generator, */
+ lua_getglobal(L, "ipairs"); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnumber(L, 0); /* and initial value */
return 3;
@@ -225,6 +236,15 @@ static int luaB_loadfile (lua_State *L) {
}
+static int luaB_dofile (lua_State *L) {
+ const char *fname = luaL_opt_string(L, 1, NULL);
+ int status = luaL_loadfile(L, fname);
+ if (status != 0) lua_error(L);
+ lua_call(L, 0, LUA_MULTRET);
+ return lua_gettop(L) - 1;
+}
+
+
static int luaB_assert (lua_State *L) {
luaL_check_any(L, 1);
if (!lua_toboolean(L, 1))
@@ -294,21 +314,27 @@ static int luaB_tostring (lua_State *L) {
static int luaB_newproxy (lua_State *L) {
- void *u;
- lua_pushnil(L); /* default argument (if there is nothing at stack[1]) */
- u = lua_newuserdata(L, sizeof(lua_CFunction)); /* create proxy */
- *(lua_CFunction *)u = luaB_newproxy; /* mark it as a proxy */
+ static const char dummy = '\0';
+ lua_settop(L, 1);
+ luaL_weakregistry(L); /* get weak registry */
+ lua_newuserdata(L, 0); /* create proxy */
if (lua_toboolean(L, 1) == 0)
return 1; /* no metatable */
- else if ((u = lua_touserdata(L, 1)) != NULL) {
- luaL_arg_check(L, *(lua_CFunction *)u == luaB_newproxy, 1, "invalid proxy");
- lua_getmetatable(L, 1); /* reuse metatable */
+ else if (lua_isboolean(L, 1)) {
+ lua_newtable(L); /* create a new metatable `m' ... */
+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
+ lua_pushudataval(L, (void *)&dummy);
+ lua_rawset(L, 2); /* weakregistry[m] = &dummy */
}
else {
- luaL_check_type(L, 1, LUA_TBOOLEAN);
- lua_newtable(L); /* create a new metatable */
+ if (lua_getmetatable(L, 1)) /* check whether registry[m] == &dummy */
+ lua_rawget(L, 2);
+ luaL_arg_check(L, (char *)lua_touserdata(L, -1) == &dummy, 1,
+ "boolean/proxy expected");
+ lua_getmetatable(L, 1); /* metatable is valid */
}
- lua_setmetatable(L, -2);
+ lua_setmetatable(L, 3);
+ lua_pushvalue(L, 3);
return 1;
}
@@ -380,7 +406,7 @@ static int luaB_require (lua_State *L) {
if (!lua_istable(L, 2)) return luaL_error(L, REQTAB " is not a table");
path = getpath(L);
lua_pushvalue(L, 1); /* check package's name in book-keeping table */
- lua_gettable(L, 2);
+ lua_rawget(L, 2);
if (!lua_isnil(L, -1)) /* is it there? */
return 0; /* package is already loaded */
else { /* must load it */
@@ -393,10 +419,10 @@ static int luaB_require (lua_State *L) {
}
switch (status) {
case 0: {
- lua_upcall(L, 0, 0); /* run loaded module */
+ lua_call(L, 0, 0); /* run loaded module */
lua_pushvalue(L, 1);
lua_pushboolean(L, 1);
- lua_settable(L, 2); /* mark it as loaded */
+ lua_rawset(L, 2); /* mark it as loaded */
return 0;
}
case LUA_ERRFILE: { /* file not found */
@@ -419,7 +445,8 @@ static const luaL_reg base_funcs[] = {
{"getglobals", luaB_getglobals},
{"setglobals", luaB_setglobals},
{"next", luaB_next},
- {"nexti", luaB_nexti},
+ {"ipairs", luaB_ipairs},
+ {"pairs", luaB_pairs},
{"print", luaB_print},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
@@ -434,6 +461,7 @@ static const luaL_reg base_funcs[] = {
{"collectgarbage", luaB_collectgarbage},
{"gcinfo", luaB_gcinfo},
{"loadfile", luaB_loadfile},
+ {"dofile", luaB_dofile},
{"loadstring", luaB_loadstring},
{"require", luaB_require},
{NULL, NULL}
@@ -531,8 +559,8 @@ static void base_open (lua_State *L) {
luaL_openlib(L, base_funcs, 0); /* open lib into global table */
lua_pushliteral(L, "_VERSION");
lua_pushliteral(L, LUA_VERSION);
- lua_settable(L, -3); /* set global _VERSION */
- lua_settable(L, -1); /* set global _G */
+ lua_rawset(L, -3); /* set global _VERSION */
+ lua_rawset(L, -1); /* set global _G */
}