浏览代码

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)
Roberto Ierusalimschy 6 年之前
父节点
当前提交
e073cbc2e5
共有 4 个文件被更改,包括 22 次插入4 次删除
  1. 6 0
      ldebug.c
  2. 2 0
      ldebug.h
  3. 4 4
      lvm.c
  4. 10 0
      testes/errors.lua

+ 6 - 0
ldebug.c

@@ -696,6 +696,12 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
 }
 
 
+l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
+  luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
+                   what, luaT_objtypename(L, o));
+}
+
+
 l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
   if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
   luaG_typeerror(L, p1, "concatenate");

+ 2 - 0
ldebug.h

@@ -24,6 +24,8 @@
 LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
 LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
                                                 const char *opname);
+LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
+                                               const char *what);
 LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
                                                   const TValue *p2);
 LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,

+ 4 - 4
lvm.c

@@ -1681,7 +1681,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         int stopnow;
         if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) {
             savestate(L, ci);  /* for the error message */
-            luaG_runerror(L, "'for' limit must be a number");
+            luaG_forerror(L, plimit, "limit");
         }
         initv = (stopnow ? 0 : ivalue(init));
         setivalue(plimit, ilimit);
@@ -1732,13 +1732,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           lua_Number ninit; lua_Number nlimit; lua_Number nstep;
           savestate(L, ci);  /* in case of errors */
           if (unlikely(!tonumber(plimit, &nlimit)))
-            luaG_runerror(L, "'for' limit must be a number");
+            luaG_forerror(L, plimit, "limit");
           setfltvalue(plimit, nlimit);
           if (unlikely(!tonumber(pstep, &nstep)))
-            luaG_runerror(L, "'for' step must be a number");
+            luaG_forerror(L, pstep, "step");
           setfltvalue(pstep, nstep);
           if (unlikely(!tonumber(init, &ninit)))
-            luaG_runerror(L, "'for' initial value must be a number");
+            luaG_forerror(L, init, "initial value");
           setfltvalue(init, luai_numsub(L, ninit, nstep));
         }
         pc += GETARG_Bx(i);

+ 10 - 0
testes/errors.lua

@@ -154,6 +154,16 @@ checkmessage("a = 24 // 0", "divide by zero")
 checkmessage("a = 1 % 0", "'n%0'")
 
 
+-- numeric for loops
+checkmessage("for i = {}, 10 do end", "table")
+checkmessage("for i = io.stdin, 10 do end", "FILE")
+checkmessage("for i = {}, 10 do end", "initial value")
+checkmessage("for i = 1, 'x', 10 do end", "string")
+checkmessage("for i = 1, {}, 10 do end", "limit")
+checkmessage("for i = 1, {} do end", "limit")
+checkmessage("for i = 1, 10, print do end", "step")
+checkmessage("for i = 1, 10, print do end", "function")
+
 -- passing light userdata instead of full userdata
 _G.D = debug
 checkmessage([[