Added macro 'luaL_pushfail'

The macro 'luaL_pushfail' documents all places in the standard libraries
that return nil to signal some kind of failure. It is defined as
'lua_pushnil'. The manual also got a notation (@fail) to document those
returns. The tests were changed to be agnostic regarding whether 'fail'
is 'nil' or 'false'.
This commit is contained in:
Roberto Ierusalimschy 2019-08-16 14:58:02 -03:00
parent ca13be9af7
commit b96b0b5abb
20 changed files with 176 additions and 154 deletions

View File

@ -249,7 +249,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
return 1; return 1;
} }
else { else {
lua_pushnil(L); luaL_pushfail(L);
if (fname) if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en)); lua_pushfstring(L, "%s: %s", fname, strerror(en));
else else
@ -291,10 +291,10 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
if (*what == 'e' && stat == 0) /* successful termination? */ if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
lua_pushnil(L); luaL_pushfail(L);
lua_pushstring(L, what); lua_pushstring(L, what);
lua_pushinteger(L, stat); lua_pushinteger(L, stat);
return 3; /* return true/nil,what,code */ return 3; /* return true/fail,what,code */
} }
} }

View File

@ -153,6 +153,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) #define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/* /*
** {====================================================== ** {======================================================
** Generic Buffer manipulation ** Generic Buffer manipulation

View File

@ -106,7 +106,7 @@ static int luaB_tonumber (lua_State *L) {
return 1; return 1;
} /* else not a number */ } /* else not a number */
} /* else not a number */ } /* else not a number */
lua_pushnil(L); /* not a number */ luaL_pushfail(L); /* not a number */
return 1; return 1;
} }
@ -308,9 +308,9 @@ static int load_aux (lua_State *L, int status, int envidx) {
return 1; return 1;
} }
else { /* error (message is on top of the stack) */ else { /* error (message is on top of the stack) */
lua_pushnil(L); luaL_pushfail(L);
lua_insert(L, -2); /* put before error message */ lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */ return 2; /* return fail plus error message */
} }
} }

View File

@ -65,7 +65,7 @@ static int db_setmetatable (lua_State *L) {
static int db_getuservalue (lua_State *L) { static int db_getuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 2, 1); int n = (int)luaL_optinteger(L, 2, 1);
if (lua_type(L, 1) != LUA_TUSERDATA) if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L); luaL_pushfail(L);
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) { else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
return 2; return 2;
@ -80,7 +80,7 @@ static int db_setuservalue (lua_State *L) {
luaL_checkany(L, 2); luaL_checkany(L, 2);
lua_settop(L, 2); lua_settop(L, 2);
if (!lua_setiuservalue(L, 1, n)) if (!lua_setiuservalue(L, 1, n))
lua_pushnil(L); luaL_pushfail(L);
return 1; return 1;
} }
@ -159,7 +159,7 @@ static int db_getinfo (lua_State *L) {
} }
else { /* stack level */ else { /* stack level */
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
lua_pushnil(L); /* level out of range */ luaL_pushfail(L); /* level out of range */
return 1; return 1;
} }
} }
@ -223,7 +223,7 @@ static int db_getlocal (lua_State *L) {
return 2; return 2;
} }
else { else {
lua_pushnil(L); /* no name (nor value) */ luaL_pushfail(L); /* no name (nor value) */
return 1; return 1;
} }
} }
@ -389,8 +389,10 @@ static int db_gethook (lua_State *L) {
char buff[5]; char buff[5];
int mask = lua_gethookmask(L1); int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1); lua_Hook hook = lua_gethook(L1);
if (hook == NULL) /* no hook? */ if (hook == NULL) { /* no hook? */
lua_pushnil(L); luaL_pushfail(L);
return 1;
}
else if (hook != hookf) /* external hook? */ else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook"); lua_pushliteral(L, "external hook");
else { /* hook table must exist */ else { /* hook table must exist */

View File

@ -153,7 +153,7 @@ static int io_type (lua_State *L) {
luaL_checkany(L, 1); luaL_checkany(L, 1);
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
if (p == NULL) if (p == NULL)
lua_pushnil(L); /* not a file */ luaL_pushfail(L); /* not a file */
else if (isclosed(p)) else if (isclosed(p))
lua_pushliteral(L, "closed file"); lua_pushliteral(L, "closed file");
else else
@ -593,7 +593,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
return luaL_fileresult(L, 0, NULL); return luaL_fileresult(L, 0, NULL);
if (!success) { if (!success) {
lua_pop(L, 1); /* remove last result */ lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */ luaL_pushfail(L); /* push nil instead */
} }
return n - first; return n - first;
} }
@ -624,9 +624,9 @@ static int io_readline (lua_State *L) {
lua_pushvalue(L, lua_upvalueindex(3 + i)); lua_pushvalue(L, lua_upvalueindex(3 + i));
n = g_read(L, p->f, 2); /* 'n' is number of results */ n = g_read(L, p->f, 2); /* 'n' is number of results */
lua_assert(n > 0); /* should return at least a nil */ lua_assert(n > 0); /* should return at least a nil */
if (!lua_isnil(L, -n)) /* read at least one value? */ if (lua_toboolean(L, -n)) /* read at least one value? */
return n; /* return them */ return n; /* return them */
else { /* first result is nil: EOF or error */ else { /* first result is false: EOF or error */
if (n > 1) { /* is there error information? */ if (n > 1) { /* is there error information? */
/* 2nd result is error message */ /* 2nd result is error message */
return luaL_error(L, "%s", lua_tostring(L, -n + 1)); return luaL_error(L, "%s", lua_tostring(L, -n + 1));
@ -782,7 +782,7 @@ static void createmeta (lua_State *L) {
static int io_noclose (lua_State *L) { static int io_noclose (lua_State *L) {
LStream *p = tolstream(L); LStream *p = tolstream(L);
p->closef = &io_noclose; /* keep file opened */ p->closef = &io_noclose; /* keep file opened */
lua_pushnil(L); luaL_pushfail(L);
lua_pushliteral(L, "cannot close standard file"); lua_pushliteral(L, "cannot close standard file");
return 2; return 2;
} }

View File

@ -77,7 +77,7 @@ static int math_toint (lua_State *L) {
lua_pushinteger(L, n); lua_pushinteger(L, n);
else { else {
luaL_checkany(L, 1); luaL_checkany(L, 1);
lua_pushnil(L); /* value is not convertible to integer */ luaL_pushfail(L); /* value is not convertible to integer */
} }
return 1; return 1;
} }
@ -235,7 +235,7 @@ static int math_type (lua_State *L) {
lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float"); lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float");
else { else {
luaL_checkany(L, 1); luaL_checkany(L, 1);
lua_pushnil(L); luaL_pushfail(L);
} }
return 1; return 1;
} }

View File

@ -408,10 +408,10 @@ static int ll_loadlib (lua_State *L) {
if (stat == 0) /* no errors? */ if (stat == 0) /* no errors? */
return 1; /* return the loaded function */ return 1; /* return the loaded function */
else { /* error; error message is on stack top */ else { /* error; error message is on stack top */
lua_pushnil(L); luaL_pushfail(L);
lua_insert(L, -2); lua_insert(L, -2);
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
return 3; /* return nil, error message, and where */ return 3; /* return fail, error message, and where */
} }
} }
@ -505,9 +505,9 @@ static int ll_searchpath (lua_State *L) {
luaL_optstring(L, 4, LUA_DIRSEP)); luaL_optstring(L, 4, LUA_DIRSEP));
if (f != NULL) return 1; if (f != NULL) return 1;
else { /* error message is on top of the stack */ else { /* error message is on top of the stack */
lua_pushnil(L); luaL_pushfail(L);
lua_insert(L, -2); lua_insert(L, -2);
return 2; /* return nil + error message */ return 2; /* return fail + error message */
} }
} }

View File

@ -744,7 +744,7 @@ static int str_find_aux (lua_State *L, int find) {
const char *p = luaL_checklstring(L, 2, &lp); const char *p = luaL_checklstring(L, 2, &lp);
size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1; size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
if (init > ls) { /* start after string's end? */ if (init > ls) { /* start after string's end? */
lua_pushnil(L); /* cannot find anything */ luaL_pushfail(L); /* cannot find anything */
return 1; return 1;
} }
/* explicit request or no special characters? */ /* explicit request or no special characters? */
@ -779,7 +779,7 @@ static int str_find_aux (lua_State *L, int find) {
} }
} while (s1++ < ms.src_end && !anchor); } while (s1++ < ms.src_end && !anchor);
} }
lua_pushnil(L); /* not found */ luaL_pushfail(L); /* not found */
return 1; return 1;
} }

View File

@ -103,7 +103,7 @@ static int utflen (lua_State *L) {
while (posi <= posj) { while (posi <= posj) {
const char *s1 = utf8_decode(s + posi, NULL, !lax); const char *s1 = utf8_decode(s + posi, NULL, !lax);
if (s1 == NULL) { /* conversion error? */ if (s1 == NULL) { /* conversion error? */
lua_pushnil(L); /* return nil ... */ luaL_pushfail(L); /* return fail ... */
lua_pushinteger(L, posi + 1); /* ... and current position */ lua_pushinteger(L, posi + 1); /* ... and current position */
return 2; return 2;
} }
@ -216,7 +216,7 @@ static int byteoffset (lua_State *L) {
if (n == 0) /* did it find given character? */ if (n == 0) /* did it find given character? */
lua_pushinteger(L, posi + 1); lua_pushinteger(L, posi + 1);
else /* no such character */ else /* no such character */
lua_pushnil(L); luaL_pushfail(L);
return 1; return 1;
} }

View File

@ -324,6 +324,7 @@ N = function (s) return (string.gsub(s, " ", "&nbsp;")) end,
NE = id, -- tag"foreignphrase", NE = id, -- tag"foreignphrase",
num = id, num = id,
["nil"] = fixed(Tag.b"nil"), ["nil"] = fixed(Tag.b"nil"),
fail = fixed(Tag.b"fail"),
Open = fixed"{", Open = fixed"{",
part = section("h1", true), part = section("h1", true),
Pat = compose(verbfixed, prepos("'", "'")), Pat = compose(verbfixed, prepos("'", "'")),

View File

@ -4058,12 +4058,15 @@ Returns 0 if the userdata does not have that value.
} }
@APIEntry{void lua_setmetatable (lua_State *L, int index);| @APIEntry{int lua_setmetatable (lua_State *L, int index);|
@apii{1,0,-} @apii{1,0,-}
Pops a table from the stack and Pops a table from the stack and
sets it as the new metatable for the value at the given index. sets it as the new metatable for the value at the given index.
(For historical reasons, this function returns an @id{int},
which now is always 1.)
} }
@APIEntry{void lua_settable (lua_State *L, int index);| @APIEntry{void lua_settable (lua_State *L, int index);|
@ -5782,7 +5785,7 @@ that will be called to close the stream
when the handle is closed or collected; when the handle is closed or collected;
this function receives the file handle as its sole argument and this function receives the file handle as its sole argument and
must return either @true, in case of success, must return either @true, in case of success,
or @nil plus an error message, in case of error. or a false value plus an error message, in case of error.
Once Lua calls this field, Once Lua calls this field,
it changes the field value to @id{NULL} it changes the field value to @id{NULL}
to signal that the handle is closed. to signal that the handle is closed.
@ -5904,6 +5907,14 @@ to its expected parameters.
For instance, a function documented as @T{foo(arg)} For instance, a function documented as @T{foo(arg)}
should not be called without an argument. should not be called without an argument.
The notation @fail means a return value representing
some kind of failure or the absence of a better value to return.
Currently, @fail is equal to @nil,
but that may change in future versions.
The recommendation is to test the success of these functions
with @T{(not status)}, instead of @T{(status == nil)}.
Currently, Lua has the following standard libraries: Currently, Lua has the following standard libraries:
@itemize{ @itemize{
@ -6108,8 +6119,8 @@ with previous results.
A return of an empty string, @nil, or no value signals the end of the chunk. A return of an empty string, @nil, or no value signals the end of the chunk.
If there are no syntactic errors, If there are no syntactic errors,
returns the compiled chunk as a function; @id{load} returns the compiled chunk as a function;
otherwise, returns @nil plus the error message. otherwise, it returns @fail plus the error message.
When you load a main chunk, When you load a main chunk,
the resulting function will always have exactly one upvalue, the resulting function will always have exactly one upvalue,
@ -6301,7 +6312,7 @@ When called with no @id{base},
If the argument is already a number or If the argument is already a number or
a string convertible to a number, a string convertible to a number,
then @id{tonumber} returns this number; then @id{tonumber} returns this number;
otherwise, it returns @nil. otherwise, it returns @fail.
The conversion of strings can result in integers or floats, The conversion of strings can result in integers or floats,
according to the lexical conventions of Lua @see{lexical}. according to the lexical conventions of Lua @see{lexical}.
@ -6315,7 +6326,7 @@ In bases @N{above 10}, the letter @Char{A} (in either upper or lower case)
@N{represents 10}, @Char{B} @N{represents 11}, and so forth, @N{represents 10}, @Char{B} @N{represents 11}, and so forth,
with @Char{Z} representing 35. with @Char{Z} representing 35.
If the string @id{e} is not a valid numeral in the given base, If the string @id{e} is not a valid numeral in the given base,
the function returns @nil. the function returns @fail.
} }
@ -6762,7 +6773,7 @@ will try to open the files
Returns the resulting name of the first file that it can Returns the resulting name of the first file that it can
open in read mode (after closing the file), open in read mode (after closing the file),
or @nil plus an error message if none succeeds. or @fail plus an error message if none succeeds.
(This error message lists all file names it tried to open.) (This error message lists all file names it tried to open.)
} }
@ -6841,7 +6852,7 @@ Looks for the first match of
@id{pattern} @see{pm} in the string @id{s}. @id{pattern} @see{pm} in the string @id{s}.
If it finds a match, then @id{find} returns the indices @N{of @T{s}} If it finds a match, then @id{find} returns the indices @N{of @T{s}}
where this occurrence starts and ends; where this occurrence starts and ends;
otherwise, it returns @nil. otherwise, it returns @fail.
A third, optional numeric argument @id{init} specifies A third, optional numeric argument @id{init} specifies
where to start the search; where to start the search;
its default value @N{is 1} and can be negative. its default value @N{is 1} and can be negative.
@ -7034,7 +7045,7 @@ Looks for the first @emph{match} of
the @id{pattern} @see{pm} in the string @id{s}. the @id{pattern} @see{pm} in the string @id{s}.
If it finds one, then @id{match} returns If it finds one, then @id{match} returns
the captures from the pattern; the captures from the pattern;
otherwise it returns @nil. otherwise it returns @fail.
If @id{pattern} specifies no captures, If @id{pattern} specifies no captures,
then the whole match is returned. then the whole match is returned.
A third, optional numeric argument @id{init} specifies A third, optional numeric argument @id{init} specifies
@ -7499,7 +7510,7 @@ Returns the number of UTF-8 characters in string @id{s}
that start between positions @id{i} and @id{j} (both inclusive). that start between positions @id{i} and @id{j} (both inclusive).
The default for @id{i} is @num{1} and for @id{j} is @num{-1}. The default for @id{i} is @num{1} and for @id{j} is @num{-1}.
If it finds any invalid byte sequence, If it finds any invalid byte sequence,
returns a false value plus the position of the first invalid byte. returns @fail plus the position of the first invalid byte.
} }
@ -7515,7 +7526,7 @@ so that @T{utf8.offset(s, -n)} gets the offset of the
@id{n}-th character from the end of the string. @id{n}-th character from the end of the string.
If the specified character is neither in the subject If the specified character is neither in the subject
nor right after its end, nor right after its end,
the function returns @nil. the function returns @fail.
As a special case, As a special case,
when @id{n} is 0 the function returns the start of the encoding when @id{n} is 0 the function returns the start of the encoding
@ -7850,7 +7861,7 @@ Returns the tangent of @id{x} (assumed to be in radians).
If the value @id{x} is convertible to an integer, If the value @id{x} is convertible to an integer,
returns that integer. returns that integer.
Otherwise, returns @nil. Otherwise, returns @fail.
} }
@ -7858,7 +7869,7 @@ Otherwise, returns @nil.
Returns @St{integer} if @id{x} is an integer, Returns @St{integer} if @id{x} is an integer,
@St{float} if it is a float, @St{float} if it is a float,
or @nil if @id{x} is not a number. or @fail if @id{x} is not a number.
} }
@ -7897,10 +7908,10 @@ three predefined file handles with their usual meanings from C:
The I/O library never closes these files. The I/O library never closes these files.
Unless otherwise stated, Unless otherwise stated,
all I/O functions return @nil on failure, all I/O functions return @fail on failure,
plus an error message as a second result and plus an error message as a second result and
a system-dependent error code as a third result, a system-dependent error code as a third result,
and some value different from @nil on success. and some non-false value on success.
On non-POSIX systems, On non-POSIX systems,
the computation of the error message and error code the computation of the error message and error code
in case of errors in case of errors
@ -8021,7 +8032,7 @@ and it is automatically removed when the program ends.
Checks whether @id{obj} is a valid file handle. Checks whether @id{obj} is a valid file handle.
Returns the string @T{"file"} if @id{obj} is an open file handle, Returns the string @T{"file"} if @id{obj} is an open file handle,
@T{"closed file"} if @id{obj} is a closed file handle, @T{"closed file"} if @id{obj} is a closed file handle,
or @nil if @id{obj} is not a file handle. or @fail if @id{obj} is not a file handle.
} }
@ -8075,7 +8086,7 @@ Reads the file @id{file},
according to the given formats, which specify what to read. according to the given formats, which specify what to read.
For each format, For each format,
the function returns a string or a number with the characters read, the function returns a string or a number with the characters read,
or @nil if it cannot read data with the specified format. or @fail if it cannot read data with the specified format.
(In this latter case, (In this latter case,
the function does not read subsequent formats.) the function does not read subsequent formats.)
When called without arguments, When called without arguments,
@ -8094,31 +8105,32 @@ is a valid prefix for a numeral;
if that prefix does not form a valid numeral if that prefix does not form a valid numeral
(e.g., an empty string, @St{0x}, or @St{3.4e-}) (e.g., an empty string, @St{0x}, or @St{3.4e-})
or it is too long (more than 200 characters), or it is too long (more than 200 characters),
it is discarded and the format returns @nil. it is discarded and the format returns @fail.
} }
@item{@St{a}| @item{@St{a}|
reads the whole file, starting at the current position. reads the whole file, starting at the current position.
On end of file, it returns the empty string. On end of file, it returns the empty string;
this format never fails.
} }
@item{@St{l}| @item{@St{l}|
reads the next line skipping the end of line, reads the next line skipping the end of line,
returning @nil on end of file. returning @fail on end of file.
This is the default format. This is the default format.
} }
@item{@St{L}| @item{@St{L}|
reads the next line keeping the end-of-line character (if present), reads the next line keeping the end-of-line character (if present),
returning @nil on end of file. returning @fail on end of file.
} }
@item{@emph{number}| @item{@emph{number}|
reads a string with up to this number of bytes, reads a string with up to this number of bytes,
returning @nil on end of file. returning @fail on end of file.
If @id{number} is zero, If @id{number} is zero,
it reads nothing and returns an empty string, it reads nothing and returns an empty string,
or @nil on end of file. or @fail on end of file.
} }
} }
@ -8139,7 +8151,7 @@ specified by the string @id{whence}, as follows:
} }
In case of success, @id{seek} returns the final file position, In case of success, @id{seek} returns the final file position,
measured in bytes from the beginning of the file. measured in bytes from the beginning of the file.
If @id{seek} fails, it returns @nil, If @id{seek} fails, it returns @fail,
plus a string describing the error. plus a string describing the error.
The default value for @id{whence} is @T{"cur"}, The default value for @id{whence} is @T{"cur"},
@ -8179,7 +8191,6 @@ Writes the value of each of its arguments to @id{file}.
The arguments must be strings or numbers. The arguments must be strings or numbers.
In case of success, this function returns @id{file}. In case of success, this function returns @id{file}.
Otherwise it returns @nil plus a string describing the error.
} }
@ -8251,7 +8262,7 @@ This function is equivalent to the @ANSI{system}.
It passes @id{command} to be executed by an operating system shell. It passes @id{command} to be executed by an operating system shell.
Its first result is @true Its first result is @true
if the command terminated successfully, if the command terminated successfully,
or @nil otherwise. or @fail otherwise.
After this first result After this first result
the function returns a string plus a number, the function returns a string plus a number,
as follows: as follows:
@ -8293,7 +8304,7 @@ closes the Lua state before exiting.
@LibEntry{os.getenv (varname)| @LibEntry{os.getenv (varname)|
Returns the value of the process environment variable @id{varname}, Returns the value of the process environment variable @id{varname},
or @nil if the variable is not defined. or @fail if the variable is not defined.
} }
@ -8301,7 +8312,7 @@ or @nil if the variable is not defined.
Deletes the file (or empty directory, on @x{POSIX} systems) Deletes the file (or empty directory, on @x{POSIX} systems)
with the given name. with the given name.
If this function fails, it returns @nil, If this function fails, it returns @fail
plus a string describing the error and the error code. plus a string describing the error and the error code.
Otherwise, it returns true. Otherwise, it returns true.
@ -8310,7 +8321,7 @@ Otherwise, it returns true.
@LibEntry{os.rename (oldname, newname)| @LibEntry{os.rename (oldname, newname)|
Renames the file or directory named @id{oldname} to @id{newname}. Renames the file or directory named @id{oldname} to @id{newname}.
If this function fails, it returns @nil, If this function fails, it returns @fail,
plus a string describing the error and the error code. plus a string describing the error and the error code.
Otherwise, it returns true. Otherwise, it returns true.
@ -8325,7 +8336,7 @@ Sets the current locale of the program.
@T{"monetary"}, @T{"numeric"}, or @T{"time"}; @T{"monetary"}, @T{"numeric"}, or @T{"time"};
the default category is @T{"all"}. the default category is @T{"all"}.
The function returns the name of the new locale, The function returns the name of the new locale,
or @nil if the request cannot be honored. or @fail if the request cannot be honored.
If @id{locale} is the empty string, If @id{locale} is the empty string,
the current locale is set to an implementation-defined native locale. the current locale is set to an implementation-defined native locale.
@ -8444,6 +8455,8 @@ the current hook function, the current hook mask,
and the current hook count, and the current hook count,
as set by the @Lid{debug.sethook} function. as set by the @Lid{debug.sethook} function.
Returns @fail if there is no active hook.
} }
@LibEntry{debug.getinfo ([thread,] f [, what])| @LibEntry{debug.getinfo ([thread,] f [, what])|
@ -8458,7 +8471,7 @@ of the given thread:
(except for tail calls, which do not count on the stack); (except for tail calls, which do not count on the stack);
and so on. and so on.
If @id{f} is a number greater than the number of active functions, If @id{f} is a number greater than the number of active functions,
then @id{getinfo} returns @nil. then @id{getinfo} returns @fail.
The returned table can contain all the fields returned by @Lid{lua_getinfo}, The returned table can contain all the fields returned by @Lid{lua_getinfo},
with the string @id{what} describing which fields to fill in. with the string @id{what} describing which fields to fill in.
@ -8496,7 +8509,8 @@ Compile-time constants may not appear in this listing,
if they were optimized away by the compiler. if they were optimized away by the compiler.
Negative indices refer to vararg arguments; Negative indices refer to vararg arguments;
@num{-1} is the first vararg argument. @num{-1} is the first vararg argument.
The function returns @nil if there is no variable with the given index, The function returns @fail
if there is no variable with the given index,
and raises an error when called with a level out of range. and raises an error when called with a level out of range.
(You can call @Lid{debug.getinfo} to check whether the level is valid.) (You can call @Lid{debug.getinfo} to check whether the level is valid.)
@ -8527,7 +8541,8 @@ Returns the registry table @see{registry}.
This function returns the name and the value of the upvalue This function returns the name and the value of the upvalue
with index @id{up} of the function @id{f}. with index @id{up} of the function @id{f}.
The function returns @nil if there is no upvalue with the given index. The function returns @fail
if there is no upvalue with the given index.
(For Lua functions, (For Lua functions,
upvalues are the external local variables that the function uses, upvalues are the external local variables that the function uses,
@ -8615,7 +8630,7 @@ and @N{level 1} is the hook function.)
This function assigns the value @id{value} to the local variable This function assigns the value @id{value} to the local variable
with index @id{local} of the function at level @id{level} of the stack. with index @id{local} of the function at level @id{level} of the stack.
The function returns @nil if there is no local The function returns @fail if there is no local
variable with the given index, variable with the given index,
and raises an error when called with a @id{level} out of range. and raises an error when called with a @id{level} out of range.
(You can call @id{getinfo} to check whether the level is valid.) (You can call @id{getinfo} to check whether the level is valid.)
@ -8638,7 +8653,7 @@ Returns @id{value}.
This function assigns the value @id{value} to the upvalue This function assigns the value @id{value} to the upvalue
with index @id{up} of the function @id{f}. with index @id{up} of the function @id{f}.
The function returns @nil if there is no upvalue The function returns @fail if there is no upvalue
with the given index. with the given index.
Otherwise, it returns the name of the upvalue. Otherwise, it returns the name of the upvalue.
@ -8653,7 +8668,7 @@ the @id{n}-th user value associated to the given @id{udata}.
@id{udata} must be a full userdata. @id{udata} must be a full userdata.
Returns @id{udata}, Returns @id{udata},
or @nil if the userdata does not have that value. or @fail if the userdata does not have that value.
} }

View File

@ -698,7 +698,7 @@ for k, v in ipairs(t) do
assert(v1 == v and p) assert(v1 == v and p)
end end
assert(debug.getuservalue(4) == nil) assert(not debug.getuservalue(4))
debug.setuservalue(b, function () return 10 end, 10) debug.setuservalue(b, function () return 10 end, 10)
collectgarbage() -- function should not be collected collectgarbage() -- function should not be collected

View File

@ -351,12 +351,12 @@ assert(g(0,0) == 30)
debug.sethook(nil); debug.sethook(nil);
assert(debug.gethook() == nil) assert(not debug.gethook())
-- minimal tests for setuservalue/getuservalue -- minimal tests for setuservalue/getuservalue
do do
assert(debug.setuservalue(io.stdin, 10) == nil) assert(not debug.setuservalue(io.stdin, 10))
local a, b = debug.getuservalue(io.stdin, 10) local a, b = debug.getuservalue(io.stdin, 10)
assert(a == nil and not b) assert(a == nil and not b)
end end
@ -414,7 +414,7 @@ end, "c")
a:f(1,2,3,4,5) a:f(1,2,3,4,5)
assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil) assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
assert(XX == 12) assert(XX == 12)
assert(debug.gethook() == nil) assert(not debug.gethook())
-- testing access to local variables in return hook (bug in 5.2) -- testing access to local variables in return hook (bug in 5.2)

View File

@ -18,7 +18,7 @@ end
local function doit (s) local function doit (s)
local f, msg = load(s) local f, msg = load(s)
if f == nil then return msg end if not f then return msg end
local cond, msg = pcall(f) local cond, msg = pcall(f)
return (not cond) and msg return (not cond) and msg
end end
@ -312,8 +312,8 @@ end
local function lineerror (s, l) local function lineerror (s, l)
local err,msg = pcall(load(s)) local err,msg = pcall(load(s))
local line = string.match(msg, ":(%d+):") local line = tonumber(string.match(msg, ":(%d+):"))
assert(tonumber(line) == l) assert(line == l or (not line and not l))
end end
lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2) lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
@ -359,7 +359,7 @@ local p = [[
g() g()
]] ]]
X=3;lineerror((p), 3) X=3;lineerror((p), 3)
X=0;lineerror((p), nil) X=0;lineerror((p), false)
X=1;lineerror((p), 2) X=1;lineerror((p), 2)
X=2;lineerror((p), 1) X=2;lineerror((p), 1)
@ -510,7 +510,7 @@ checksyntax("a\1a = 1", "", "<\\1>", 1)
checksyntax("\255a = 1", "", "<\\255>", 1) checksyntax("\255a = 1", "", "<\\255>", 1)
doit('I = load("a=9+"); a=3') doit('I = load("a=9+"); a=3')
assert(a==3 and I == nil) assert(a==3 and not I)
print('+') print('+')
lim = 1000 lim = 1000

View File

@ -184,7 +184,7 @@ three
local f <close> = assert(io.open(file, "r")) local f <close> = assert(io.open(file, "r"))
-- second item failing -- second item failing
l1, n1, n2, dummy = f:read("l", "n", "n", "l") l1, n1, n2, dummy = f:read("l", "n", "n", "l")
assert(l1 == "a line" and n1 == nil) assert(l1 == "a line" and not n1)
end end
assert(os.remove(file)) assert(os.remove(file))
@ -228,7 +228,7 @@ assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e") assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
do -- attempt to read too long number do -- attempt to read too long number
assert(f:read("n") == nil) -- fails assert(not f:read("n")) -- fails
local s = f:read("L") -- read rest of line local s = f:read("L") -- read rest of line
assert(string.find(s, "^00*\n$")) -- lots of 0's left assert(string.find(s, "^00*\n$")) -- lots of 0's left
end end
@ -314,13 +314,13 @@ assert(io.read() == "fourth_line")
assert(io.read() == "") -- empty line assert(io.read() == "") -- empty line
assert(io.read('n') == 3450) assert(io.read('n') == 3450)
assert(io.read(1) == '\n') assert(io.read(1) == '\n')
assert(io.read(0) == nil) -- end of file assert(not io.read(0)) -- end of file
assert(io.read(1) == nil) -- end of file assert(not io.read(1)) -- end of file
assert(io.read(30000) == nil) -- end of file assert(not io.read(30000)) -- end of file
assert(({io.read(1)})[2] == undef) assert(({io.read(1)})[2] == undef)
assert(io.read() == nil) -- end of file assert(not io.read()) -- end of file
assert(({io.read()})[2] == undef) assert(({io.read()})[2] == undef)
assert(io.read('n') == nil) -- end of file assert(not io.read('n')) -- end of file
assert(({io.read('n')})[2] == undef) assert(({io.read('n')})[2] == undef)
assert(io.read('a') == '') -- end of file (OK for 'a') assert(io.read('a') == '') -- end of file (OK for 'a')
assert(io.read('a') == '') -- end of file (OK for 'a') assert(io.read('a') == '') -- end of file (OK for 'a')
@ -356,7 +356,7 @@ assert(io.read(string.len(t)) == t)
assert(io.read(1) == ' ') assert(io.read(1) == ' ')
assert(io.read(0)) assert(io.read(0))
assert(io.read('a') == ';end of file\n') assert(io.read('a') == ';end of file\n')
assert(io.read(0) == nil) assert(not io.read(0))
assert(io.close(io.input())) assert(io.close(io.input()))
@ -364,7 +364,7 @@ assert(io.close(io.input()))
do do
local function ismsg (m) local function ismsg (m)
-- error message is not a code number -- error message is not a code number
return (type(m) == "string" and tonumber(m) == nil) return (type(m) == "string" and not tonumber(m))
end end
-- read -- read
@ -393,7 +393,7 @@ assert(io.read"L" == "\n")
assert(io.read"L" == "\n") assert(io.read"L" == "\n")
assert(io.read"L" == "line\n") assert(io.read"L" == "line\n")
assert(io.read"L" == "other") assert(io.read"L" == "other")
assert(io.read"L" == nil) assert(not io.read"L")
io.input():close() io.input():close()
local f = assert(io.open(file)) local f = assert(io.open(file))
@ -462,7 +462,7 @@ end
-- test for multipe arguments in 'lines' -- test for multipe arguments in 'lines'
io.output(file); io.write"0123456789\n":close() io.output(file); io.write"0123456789\n":close()
for a,b in io.lines(file, 1, 1) do for a,b in io.lines(file, 1, 1) do
if a == "\n" then assert(b == nil) if a == "\n" then assert(not b)
else assert(tonumber(a) == tonumber(b) - 1) else assert(tonumber(a) == tonumber(b) - 1)
end end
end end
@ -473,13 +473,13 @@ end
for a,b,c in io.lines(file, "a", 0, 1) do for a,b,c in io.lines(file, "a", 0, 1) do
if a == "" then break end if a == "" then break end
assert(a == "0123456789\n" and b == nil and c == nil) assert(a == "0123456789\n" and not b and not c)
end end
collectgarbage() -- to close file in previous iteration collectgarbage() -- to close file in previous iteration
io.output(file); io.write"00\n10\n20\n30\n40\n":close() io.output(file); io.write"00\n10\n20\n30\n40\n":close()
for a, b in io.lines(file, "n", "n") do for a, b in io.lines(file, "n", "n") do
if a == 40 then assert(b == nil) if a == 40 then assert(not b)
else assert(a == b - 10) else assert(a == b - 10)
end end
end end
@ -654,7 +654,7 @@ and the rest of the file
io.input(file) io.input(file)
local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10) local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
assert(io.close(io.input())) assert(io.close(io.input()))
assert(_ == ' ' and __ == nil) assert(_ == ' ' and not __)
assert(type(a) == 'number' and a==123.4 and b==-56e-2) assert(type(a) == 'number' and a==123.4 and b==-56e-2)
assert(d=='second line' and e=='third line') assert(d=='second line' and e=='third line')
assert(h==[[ assert(h==[[
@ -706,7 +706,7 @@ if not _soft then
io.input():seek('set', 0) io.input():seek('set', 0)
y = io.read() -- huge line y = io.read() -- huge line
assert(x == y..'\n'..io.read()) assert(x == y..'\n'..io.read())
assert(io.read() == nil) assert(not io.read())
io.close(io.input()) io.close(io.input())
assert(os.remove(file)) assert(os.remove(file))
x = nil; y = nil x = nil; y = nil

View File

@ -281,7 +281,7 @@ if os.setlocale("pt_BR") or os.setlocale("ptb") then
assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1) assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1)
assert(tonumber"inf" == nil and tonumber"NAN" == nil) assert(not tonumber"inf" and not tonumber"NAN")
assert(assert(load(string.format("return %q", 4.51)))() == 4.51) assert(assert(load(string.format("return %q", 4.51)))() == 4.51)

View File

@ -39,7 +39,7 @@ do
end end
assert(math.type(0) == "integer" and math.type(0.0) == "float" assert(math.type(0) == "integer" and math.type(0.0) == "float"
and math.type("10") == nil) and not math.type("10"))
local function checkerror (msg, f, ...) local function checkerror (msg, f, ...)
@ -381,17 +381,17 @@ assert(tonumber(1/0) == 1/0)
-- 'tonumber' with strings -- 'tonumber' with strings
assert(tonumber("0") == 0) assert(tonumber("0") == 0)
assert(tonumber("") == nil) assert(not tonumber(""))
assert(tonumber(" ") == nil) assert(not tonumber(" "))
assert(tonumber("-") == nil) assert(not tonumber("-"))
assert(tonumber(" -0x ") == nil) assert(not tonumber(" -0x "))
assert(tonumber{} == nil) assert(not tonumber{})
assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
tonumber'.01' == 0.01 and tonumber'-1.' == -1 and tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
tonumber'+1.' == 1) tonumber'+1.' == 1)
assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and assert(not tonumber'+ 0.01' and not tonumber'+.e1' and
tonumber'1e' == nil and tonumber'1.0e+' == nil and not tonumber'1e' and not tonumber'1.0e+' and
tonumber'.' == nil) not tonumber'.')
assert(tonumber('-012') == -010-2) assert(tonumber('-012') == -010-2)
assert(tonumber('-1.2e2') == - - -120) assert(tonumber('-1.2e2') == - - -120)
@ -445,45 +445,45 @@ local function f (...)
end end
end end
assert(f(tonumber('fFfa', 15)) == nil) assert(not f(tonumber('fFfa', 15)))
assert(f(tonumber('099', 8)) == nil) assert(not f(tonumber('099', 8)))
assert(f(tonumber('1\0', 2)) == nil) assert(not f(tonumber('1\0', 2)))
assert(f(tonumber('', 8)) == nil) assert(not f(tonumber('', 8)))
assert(f(tonumber(' ', 9)) == nil) assert(not f(tonumber(' ', 9)))
assert(f(tonumber(' ', 9)) == nil) assert(not f(tonumber(' ', 9)))
assert(f(tonumber('0xf', 10)) == nil) assert(not f(tonumber('0xf', 10)))
assert(f(tonumber('inf')) == nil) assert(not f(tonumber('inf')))
assert(f(tonumber(' INF ')) == nil) assert(not f(tonumber(' INF ')))
assert(f(tonumber('Nan')) == nil) assert(not f(tonumber('Nan')))
assert(f(tonumber('nan')) == nil) assert(not f(tonumber('nan')))
assert(f(tonumber(' ')) == nil) assert(not f(tonumber(' ')))
assert(f(tonumber('')) == nil) assert(not f(tonumber('')))
assert(f(tonumber('1 a')) == nil) assert(not f(tonumber('1 a')))
assert(f(tonumber('1 a', 2)) == nil) assert(not f(tonumber('1 a', 2)))
assert(f(tonumber('1\0')) == nil) assert(not f(tonumber('1\0')))
assert(f(tonumber('1 \0')) == nil) assert(not f(tonumber('1 \0')))
assert(f(tonumber('1\0 ')) == nil) assert(not f(tonumber('1\0 ')))
assert(f(tonumber('e1')) == nil) assert(not f(tonumber('e1')))
assert(f(tonumber('e 1')) == nil) assert(not f(tonumber('e 1')))
assert(f(tonumber(' 3.4.5 ')) == nil) assert(not f(tonumber(' 3.4.5 ')))
-- testing 'tonumber' for invalid hexadecimal formats -- testing 'tonumber' for invalid hexadecimal formats
assert(tonumber('0x') == nil) assert(not tonumber('0x'))
assert(tonumber('x') == nil) assert(not tonumber('x'))
assert(tonumber('x3') == nil) assert(not tonumber('x3'))
assert(tonumber('0x3.3.3') == nil) -- two decimal points assert(not tonumber('0x3.3.3')) -- two decimal points
assert(tonumber('00x2') == nil) assert(not tonumber('00x2'))
assert(tonumber('0x 2') == nil) assert(not tonumber('0x 2'))
assert(tonumber('0 x2') == nil) assert(not tonumber('0 x2'))
assert(tonumber('23x') == nil) assert(not tonumber('23x'))
assert(tonumber('- 0xaa') == nil) assert(not tonumber('- 0xaa'))
assert(tonumber('-0xaaP ') == nil) -- no exponent assert(not tonumber('-0xaaP ')) -- no exponent
assert(tonumber('0x0.51p') == nil) assert(not tonumber('0x0.51p'))
assert(tonumber('0x5p+-2') == nil) assert(not tonumber('0x5p+-2'))
-- testing hexadecimal numerals -- testing hexadecimal numerals
@ -705,19 +705,19 @@ do -- testing floor & ceil
assert(eqT(math.tointeger(maxint), maxint)) assert(eqT(math.tointeger(maxint), maxint))
assert(eqT(math.tointeger(maxint .. ""), maxint)) assert(eqT(math.tointeger(maxint .. ""), maxint))
assert(eqT(math.tointeger(minint + 0.0), minint)) assert(eqT(math.tointeger(minint + 0.0), minint))
assert(math.tointeger(0.0 - minint) == nil) assert(not math.tointeger(0.0 - minint))
assert(math.tointeger(math.pi) == nil) assert(not math.tointeger(math.pi))
assert(math.tointeger(-math.pi) == nil) assert(not math.tointeger(-math.pi))
assert(math.floor(math.huge) == math.huge) assert(math.floor(math.huge) == math.huge)
assert(math.ceil(math.huge) == math.huge) assert(math.ceil(math.huge) == math.huge)
assert(math.tointeger(math.huge) == nil) assert(not math.tointeger(math.huge))
assert(math.floor(-math.huge) == -math.huge) assert(math.floor(-math.huge) == -math.huge)
assert(math.ceil(-math.huge) == -math.huge) assert(math.ceil(-math.huge) == -math.huge)
assert(math.tointeger(-math.huge) == nil) assert(not math.tointeger(-math.huge))
assert(math.tointeger("34.0") == 34) assert(math.tointeger("34.0") == 34)
assert(math.tointeger("34.3") == nil) assert(not math.tointeger("34.3"))
assert(math.tointeger({}) == nil) assert(not math.tointeger({}))
assert(math.tointeger(0/0) == nil) -- NaN assert(not math.tointeger(0/0)) -- NaN
end end

View File

@ -28,10 +28,10 @@ a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
assert(a == 9 and b == 11); assert(a == 9 and b == 11);
a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position
assert(a == 11 and b == 11) assert(a == 11 and b == 11)
assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending assert(not string.find('a\0a\0a\0a\0\0ab', 'b\0')) -- check ending
assert(string.find('', '\0') == nil) assert(not string.find('', '\0'))
assert(string.find('alo123alo', '12') == 4) assert(string.find('alo123alo', '12') == 4)
assert(string.find('alo123alo', '^12') == nil) assert(not string.find('alo123alo', '^12'))
assert(string.match("aaab", ".*b") == "aaab") assert(string.match("aaab", ".*b") == "aaab")
assert(string.match("aaa", ".*a") == "aaa") assert(string.match("aaa", ".*a") == "aaa")
@ -57,17 +57,17 @@ assert(f('aaa', 'ab*a') == 'aa')
assert(f('aba', 'ab*a') == 'aba') assert(f('aba', 'ab*a') == 'aba')
assert(f('aaab', 'a+') == 'aaa') assert(f('aaab', 'a+') == 'aaa')
assert(f('aaa', '^.+$') == 'aaa') assert(f('aaa', '^.+$') == 'aaa')
assert(f('aaa', 'b+') == nil) assert(not f('aaa', 'b+'))
assert(f('aaa', 'ab+a') == nil) assert(not f('aaa', 'ab+a'))
assert(f('aba', 'ab+a') == 'aba') assert(f('aba', 'ab+a') == 'aba')
assert(f('a$a', '.$') == 'a') assert(f('a$a', '.$') == 'a')
assert(f('a$a', '.%$') == 'a$') assert(f('a$a', '.%$') == 'a$')
assert(f('a$a', '.$.') == 'a$a') assert(f('a$a', '.$.') == 'a$a')
assert(f('a$a', '$$') == nil) assert(not f('a$a', '$$'))
assert(f('a$b', 'a$') == nil) assert(not f('a$b', 'a$'))
assert(f('a$a', '$') == '') assert(f('a$a', '$') == '')
assert(f('', 'b*') == '') assert(f('', 'b*') == '')
assert(f('aaa', 'bb*') == nil) assert(not f('aaa', 'bb*'))
assert(f('aaab', 'a-') == '') assert(f('aaab', 'a-') == '')
assert(f('aaa', '^.-$') == 'aaa') assert(f('aaa', '^.-$') == 'aaa')
assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab') assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab')
@ -101,7 +101,7 @@ end
assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o") assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3') assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
assert(f1('=======', '^(=*)=%1$') == '=======') assert(f1('=======', '^(=*)=%1$') == '=======')
assert(string.match('==========', '^([=]*)=%1$') == nil) assert(not string.match('==========', '^([=]*)=%1$'))
local function range (i, j) local function range (i, j)
if i <= j then if i <= j then
@ -135,7 +135,7 @@ print('+');
assert(string.match("alo xyzK", "(%w+)K") == "xyz") assert(string.match("alo xyzK", "(%w+)K") == "xyz")
assert(string.match("254 K", "(%d*)K") == "") assert(string.match("254 K", "(%d*)K") == "")
assert(string.match("alo ", "(%w*)$") == "") assert(string.match("alo ", "(%w*)$") == "")
assert(string.match("alo ", "(%w+)$") == nil) assert(not string.match("alo ", "(%w+)$"))
assert(string.find("(álo)", "%(á") == 1) assert(string.find("(álo)", "%(á") == 1)
local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$") local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$")
assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil) assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil)
@ -209,7 +209,7 @@ assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
function isbalanced (s) function isbalanced (s)
return string.find(string.gsub(s, "%b()", ""), "[()]") == nil return not string.find(string.gsub(s, "%b()", ""), "[()]")
end end
assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a")) assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a"))

View File

@ -56,13 +56,13 @@ a,b = string.find("123456789", "345")
assert(string.sub("123456789", a, b) == "345") assert(string.sub("123456789", a, b) == "345")
assert(string.find("1234567890123456789", "345", 3) == 3) assert(string.find("1234567890123456789", "345", 3) == 3)
assert(string.find("1234567890123456789", "345", 4) == 13) assert(string.find("1234567890123456789", "345", 4) == 13)
assert(string.find("1234567890123456789", "346", 4) == nil) assert(not string.find("1234567890123456789", "346", 4))
assert(string.find("1234567890123456789", ".45", -9) == 13) assert(string.find("1234567890123456789", ".45", -9) == 13)
assert(string.find("abcdefg", "\0", 5, 1) == nil) assert(not string.find("abcdefg", "\0", 5, 1))
assert(string.find("", "") == 1) assert(string.find("", "") == 1)
assert(string.find("", "", 1) == 1) assert(string.find("", "", 1) == 1)
assert(not string.find("", "", 2)) assert(not string.find("", "", 2))
assert(string.find('', 'aaa', 1) == nil) assert(not string.find('', 'aaa', 1))
assert(('alo(.)alo'):find('(.)', 1, 1) == 4) assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
assert(string.len("") == 0) assert(string.len("") == 0)

View File

@ -30,8 +30,8 @@ local function checksyntax (s, t)
assert(assert(load(ts))() == s) assert(assert(load(ts))() == s)
end end
assert(utf8.offset("alo", 5) == nil) assert(not utf8.offset("alo", 5))
assert(utf8.offset("alo", -4) == nil) assert(not utf8.offset("alo", -4))
-- 'check' makes several tests over the validity of string 's'. -- 'check' makes several tests over the validity of string 's'.
-- 't' is the list of codepoints of 's'. -- 't' is the list of codepoints of 's'.