new functions `dofile' and `pairs'; correct way to check proxies

This commit is contained in:
Roberto Ierusalimschy 2002-06-25 16:19:33 -03:00
parent 78c507b7b8
commit 25dc9b7faf
1 changed files with 50 additions and 22 deletions

View File

@ -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 */
}