diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-30 15:46:56 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-30 15:46:56 -0300 |
commit | e073cbc2e538369e0611abfc9948f301aea6aef3 (patch) | |
tree | 6ef30a285092e8bcc15021b1d857a62dbab36fd6 | |
parent | 2316ec4c24a475e091ec3153a5bd908801a3a109 (diff) | |
download | lua-e073cbc2e538369e0611abfc9948f301aea6aef3.tar.gz lua-e073cbc2e538369e0611abfc9948f301aea6aef3.tar.bz2 lua-e073cbc2e538369e0611abfc9948f301aea6aef3.zip |
Better error messages for invalid operands in numeric 'for'
"Better" and similar to error messages for invalid function arguments.
*old message: 'for' limit must be a number
*new message: bad 'for' limit (number expected, got table)
-rw-r--r-- | ldebug.c | 6 | ||||
-rw-r--r-- | ldebug.h | 2 | ||||
-rw-r--r-- | lvm.c | 8 | ||||
-rw-r--r-- | testes/errors.lua | 10 |
4 files changed, 22 insertions, 4 deletions
@@ -696,6 +696,12 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
696 | } | 696 | } |
697 | 697 | ||
698 | 698 | ||
699 | l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { | ||
700 | luaG_runerror(L, "bad 'for' %s (number expected, got %s)", | ||
701 | what, luaT_objtypename(L, o)); | ||
702 | } | ||
703 | |||
704 | |||
699 | l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { | 705 | l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { |
700 | if (ttisstring(p1) || cvt2str(p1)) p1 = p2; | 706 | if (ttisstring(p1) || cvt2str(p1)) p1 = p2; |
701 | luaG_typeerror(L, p1, "concatenate"); | 707 | luaG_typeerror(L, p1, "concatenate"); |
@@ -24,6 +24,8 @@ | |||
24 | LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); | 24 | LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); |
25 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, | 25 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, |
26 | const char *opname); | 26 | const char *opname); |
27 | LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, | ||
28 | const char *what); | ||
27 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, | 29 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, |
28 | const TValue *p2); | 30 | const TValue *p2); |
29 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, | 31 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, |
@@ -1681,7 +1681,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1681 | int stopnow; | 1681 | int stopnow; |
1682 | if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) { | 1682 | if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) { |
1683 | savestate(L, ci); /* for the error message */ | 1683 | savestate(L, ci); /* for the error message */ |
1684 | luaG_runerror(L, "'for' limit must be a number"); | 1684 | luaG_forerror(L, plimit, "limit"); |
1685 | } | 1685 | } |
1686 | initv = (stopnow ? 0 : ivalue(init)); | 1686 | initv = (stopnow ? 0 : ivalue(init)); |
1687 | setivalue(plimit, ilimit); | 1687 | setivalue(plimit, ilimit); |
@@ -1732,13 +1732,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1732 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; | 1732 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |
1733 | savestate(L, ci); /* in case of errors */ | 1733 | savestate(L, ci); /* in case of errors */ |
1734 | if (unlikely(!tonumber(plimit, &nlimit))) | 1734 | if (unlikely(!tonumber(plimit, &nlimit))) |
1735 | luaG_runerror(L, "'for' limit must be a number"); | 1735 | luaG_forerror(L, plimit, "limit"); |
1736 | setfltvalue(plimit, nlimit); | 1736 | setfltvalue(plimit, nlimit); |
1737 | if (unlikely(!tonumber(pstep, &nstep))) | 1737 | if (unlikely(!tonumber(pstep, &nstep))) |
1738 | luaG_runerror(L, "'for' step must be a number"); | 1738 | luaG_forerror(L, pstep, "step"); |
1739 | setfltvalue(pstep, nstep); | 1739 | setfltvalue(pstep, nstep); |
1740 | if (unlikely(!tonumber(init, &ninit))) | 1740 | if (unlikely(!tonumber(init, &ninit))) |
1741 | luaG_runerror(L, "'for' initial value must be a number"); | 1741 | luaG_forerror(L, init, "initial value"); |
1742 | setfltvalue(init, luai_numsub(L, ninit, nstep)); | 1742 | setfltvalue(init, luai_numsub(L, ninit, nstep)); |
1743 | } | 1743 | } |
1744 | pc += GETARG_Bx(i); | 1744 | pc += GETARG_Bx(i); |
diff --git a/testes/errors.lua b/testes/errors.lua index 142e8b33..74975e31 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
@@ -154,6 +154,16 @@ checkmessage("a = 24 // 0", "divide by zero") | |||
154 | checkmessage("a = 1 % 0", "'n%0'") | 154 | checkmessage("a = 1 % 0", "'n%0'") |
155 | 155 | ||
156 | 156 | ||
157 | -- numeric for loops | ||
158 | checkmessage("for i = {}, 10 do end", "table") | ||
159 | checkmessage("for i = io.stdin, 10 do end", "FILE") | ||
160 | checkmessage("for i = {}, 10 do end", "initial value") | ||
161 | checkmessage("for i = 1, 'x', 10 do end", "string") | ||
162 | checkmessage("for i = 1, {}, 10 do end", "limit") | ||
163 | checkmessage("for i = 1, {} do end", "limit") | ||
164 | checkmessage("for i = 1, 10, print do end", "step") | ||
165 | checkmessage("for i = 1, 10, print do end", "function") | ||
166 | |||
157 | -- passing light userdata instead of full userdata | 167 | -- passing light userdata instead of full userdata |
158 | _G.D = debug | 168 | _G.D = debug |
159 | checkmessage([[ | 169 | checkmessage([[ |