Janitorial work

- Several details in 'lcode.c'
- A few more tests for code generation
- Bug in assert in 'lcode.c' ("=" x "==")
- Comments in 'lopcodes.h' and 'ltable.c'
diff --git a/lcode.c b/lcode.c
index bc86793..abb8a81 100644
--- a/lcode.c
+++ b/lcode.c
@@ -359,12 +359,12 @@
   Proto *f = fs->f;
   int pc = fs->pc - 1;  /* last instruction coded */
   if (f->lineinfo[pc] != ABSLINEINFO) {  /* relative line info? */
-    fs->previousline -= f->lineinfo[pc];  /* last line saved */
-    fs->iwthabs--;
+    fs->previousline -= f->lineinfo[pc];  /* correct last line saved */
+    fs->iwthabs--;  /* undo previous increment */
   }
   else {  /* absolute line information */
+    lua_assert(f->abslineinfo[fs->nabslineinfo - 1].pc == pc);
     fs->nabslineinfo--;  /* remove it */
-    lua_assert(f->abslineinfo[fs->nabslineinfo].pc = pc);
     fs->iwthabs = MAXIWTHABS + 1;  /* force next line info to be absolute */
   }
 }
@@ -626,12 +626,12 @@
 
 
 /*
-** Check whether 'i' can be stored in an 'sC' operand.
-** Equivalent to (0 <= int2sC(i) && int2sC(i) <= MAXARG_C)
-** but without risk of overflows in the addition.
+** Check whether 'i' can be stored in an 'sC' operand. Equivalent to
+** (0 <= int2sC(i) && int2sC(i) <= MAXARG_C) but without risk of
+** overflows in the hidden addition inside 'int2sC'.
 */
 static int fitsC (lua_Integer i) {
-  return (-OFFSET_sC <= i && i <= MAXARG_C - OFFSET_sC);
+  return (l_castS2U(i) + OFFSET_sC <= cast_uint(MAXARG_C));
 }
 
 
@@ -1213,15 +1213,6 @@
 
 
 /*
-** Check whether expression 'e' and its negation are literal integers
-** in proper range to fit in register sC
-*/
-static int isSCintN (expdesc *e) {
-  return luaK_isKint(e) && fitsC(e->u.ival) && fitsC(-e->u.ival);
-}
-
-
-/*
 ** Check whether expression 'e' is a literal integer or float in
 ** proper range to fit in a register (sB or sC).
 */
@@ -1382,15 +1373,25 @@
 }
 
 
-/* Code binary operators negating the immediate operand for the
-** opcode. For the metamethod, 'v2' must keep its original value.
+/* Try to code a binary operator negating its second operand.
+** For the metamethod, 2nd operand must keep its original value.
 */
-static void finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
+static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
                              OpCode op, int line, TMS event) {
-  int v2 = cast_int(e2->u.ival);
-  finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
-  /* correct metamethod argument */
-  SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
+  if (!luaK_isKint(e2))
+    return 0;  /* not an integer constant */
+  else {
+    lua_Integer i2 = e2->u.ival;
+    if (!(fitsC(i2) && fitsC(-i2)))
+      return 0;  /* not in the proper range */
+    else {  /* operating a small integer constant */
+      int v2 = cast_int(i2);
+      finishbinexpval(fs, e1, e2, op, int2sC(-v2), 0, line, OP_MMBINI, event);
+      /* correct metamethod argument */
+      SETARG_B(fs->f->code[fs->pc - 1], int2sC(v2));
+      return 1;  /* successfully coded */
+    }
+  }
 }
 
 
@@ -1647,11 +1648,8 @@
       break;
     }
     case OPR_SUB: {
-      if (isSCintN(e2)) {  /* subtracting a small integer constant? */
-        /* code it as (r1 + -I) */
-        finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB);
-        break;
-      }
+      if (finishbinexpneg(fs, e1, e2, OP_ADDI, line, TM_SUB))
+        break; /* coded as (r1 + -I) */
       /* ELSE *//* FALLTHROUGH */
     }
     case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: {
@@ -1667,16 +1665,15 @@
         swapexps(e1, e2);
         codebini(fs, OP_SHLI, e1, e2, 1, line, TM_SHL);  /* I << r2 */
       }
-      else if (isSCintN(e2)) {  /* shifting by a small integer constant? */
-        /* code it as (r1 >> -I) */
-        finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL);
+      else if (finishbinexpneg(fs, e1, e2, OP_SHRI, line, TM_SHL)) {
+        /* coded as (r1 >> -I) */;
       }
       else  /* regular case (two registers) */
        codebinexpval(fs, OP_SHL, e1, e2, line);
       break;
     }
     case OPR_SHR: {
-      if (isSCintN(e2))
+      if (isSCint(e2))
         codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR);  /* r1 >> I */
       else  /* regular case (two registers) */
         codebinexpval(fs, OP_SHR, e1, e2, line);
diff --git a/lopcodes.h b/lopcodes.h
index 9524170..443a71e 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -221,7 +221,7 @@
 
 OP_SELF,/*	A B C	R(A+1) := R(B); R(A) := R(B)[RK(C):string]	*/
 
-OP_ADDI,/*	A B sC	R(A) := R(B) + C				*/
+OP_ADDI,/*	A B sC	R(A) := R(B) + sC				*/
 
 OP_ADDK,/*	A B C	R(A) := R(B) + K(C)				*/
 OP_SUBK,/*	A B C	R(A) := R(B) - K(C)				*/
@@ -235,8 +235,8 @@
 OP_BORK,/*	A B C	R(A) := R(B) | K(C):integer			*/
 OP_BXORK,/*	A B C	R(A) := R(B) ~ K(C):integer			*/
 
-OP_SHRI,/*	A B sC	R(A) := R(B) >> C				*/
-OP_SHLI,/*	A B sC	R(A) := C << R(B)				*/
+OP_SHRI,/*	A B sC	R(A) := R(B) >> sC				*/
+OP_SHLI,/*	A B sC	R(A) := sC << R(B)				*/
 
 OP_ADD,/*	A B C	R(A) := R(B) + R(C)				*/
 OP_SUB,/*	A B C	R(A) := R(B) - R(C)				*/
@@ -253,7 +253,7 @@
 OP_SHR,/*	A B C	R(A) := R(B) >> R(C)				*/
 
 OP_MMBIN,/*	A B C	call C metamethod over R(A) and R(B)		*/
-OP_MMBINI,/*	A B C	call C metamethod over R(A) and B		*/
+OP_MMBINI,/*	A sB C	call C metamethod over R(A) and sB		*/
 OP_MMBINK,/*	A B C	call C metamethod over R(A) and K(B)		*/
 
 OP_UNM,/*	A B	R(A) := -R(B)					*/
diff --git a/ltable.c b/ltable.c
index d8ff3d8..5561d45 100644
--- a/ltable.c
+++ b/ltable.c
@@ -833,39 +833,41 @@
 ** and 'maxinteger' if t[maxinteger] is present.)
 ** (In the next explanation, we use Lua indices, that is, with base 1.
 ** The code itself uses base 0 when indexing the array part of the table.)
-** The code starts with 'limit', a position in the array part that may
-** be a boundary.
+** The code starts with 'limit = t->alimit', a position in the array
+** part that may be a boundary.
+**
 ** (1) If 't[limit]' is empty, there must be a boundary before it.
-** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1'
+** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1'
 ** is present. If so, it is a boundary. Otherwise, do a binary search
 ** between 0 and limit to find a boundary. In both cases, try to
-** use this boundary as the new 'limit', as a hint for the next call.
+** use this boundary as the new 'alimit', as a hint for the next call.
+**
 ** (2) If 't[limit]' is not empty and the array has more elements
 ** after 'limit', try to find a boundary there. Again, try first
 ** the special case (which should be quite frequent) where 'limit+1'
 ** is empty, so that 'limit' is a boundary. Otherwise, check the
-** last element of the array part (set it as a new limit). If it is empty,
-** there must be a boundary between the old limit (present) and the new
-** limit (absent), which is found with a binary search. (This boundary
-** always can be a new limit.)
+** last element of the array part. If it is empty, there must be a
+** boundary between the old limit (present) and the last element
+** (absent), which is found with a binary search. (This boundary always
+** can be a new limit.)
+**
 ** (3) The last case is when there are no elements in the array part
 ** (limit == 0) or its last element (the new limit) is present.
-** In this case, must check the hash part. If there is no hash part,
-** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is
-** a boundary. Finally, if 'limit+1' is present, call 'hash_search'
-** to find a boundary in the hash part of the table. (In those
-** cases, the boundary is not inside the array part, and therefore
-** cannot be used as a new limit.)
+** In this case, must check the hash part. If there is no hash part
+** or 'limit+1' is absent, 'limit' is a boundary.  Otherwise, call
+** 'hash_search' to find a boundary in the hash part of the table.
+** (In those cases, the boundary is not inside the array part, and
+** therefore cannot be used as a new limit.)
 */
 lua_Unsigned luaH_getn (Table *t) {
   unsigned int limit = t->alimit;
-  if (limit > 0 && isempty(&t->array[limit - 1])) {
-    /* (1) there must be a boundary before 'limit' */
+  if (limit > 0 && isempty(&t->array[limit - 1])) {  /* (1)? */
+    /* there must be a boundary before 'limit' */
     if (limit >= 2 && !isempty(&t->array[limit - 2])) {
       /* 'limit - 1' is a boundary; can it be a new limit? */
       if (ispow2realasize(t) && !ispow2(limit - 1)) {
         t->alimit = limit - 1;
-        setnorealasize(t);
+        setnorealasize(t);  /* now 'alimit' is not the real size */
       }
       return limit - 1;
     }
@@ -880,8 +882,8 @@
     }
   }
   /* 'limit' is zero or present in table */
-  if (!limitequalsasize(t)) {
-    /* (2) 'limit' > 0 and array has more elements after 'limit' */
+  if (!limitequalsasize(t)) {  /* (2)? */
+    /* 'limit' > 0 and array has more elements after 'limit' */
     if (isempty(&t->array[limit]))  /* 'limit + 1' is empty? */
       return limit;  /* this is the boundary */
     /* else, try last element in the array */
@@ -899,7 +901,7 @@
   lua_assert(limit == luaH_realasize(t) &&
              (limit == 0 || !isempty(&t->array[limit - 1])));
   if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1))))
-    return limit;  /* 'limit + 1' is absent... */
+    return limit;  /* 'limit + 1' is absent */
   else  /* 'limit + 1' is also present */
     return hash_search(t, limit);
 }
@@ -908,6 +910,8 @@
 
 #if defined(LUA_DEBUG)
 
+/* export these functions for the test library */
+
 Node *luaH_mainposition (const Table *t, const TValue *key) {
   return mainpositionTV(t, key);
 }
diff --git a/testes/code.lua b/testes/code.lua
index ab531fa..e12f3f9 100644
--- a/testes/code.lua
+++ b/testes/code.lua
@@ -306,8 +306,10 @@
 checkR(function (x) return x % (100 - 10) end, 91, 1,
          'MODK', 'MMBINK', 'RETURN1')
 checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1')
-checkR(function (x) return x << 2 end, 10, 40, 'SHRI', 'MMBINI', 'RETURN1')
-checkR(function (x) return x >> 2 end, 8, 2, 'SHRI', 'MMBINI', 'RETURN1')
+checkR(function (x) return x << 127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
+checkR(function (x) return x << -127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
+checkR(function (x) return x >> 128 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
+checkR(function (x) return x >> -127 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
 checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1')
 checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1')
 checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1')
@@ -331,6 +333,7 @@
 check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1')
 check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1')
 check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1')
+check(function (x) return x << 128 end, 'LOADI', 'SHL', 'MMBIN', 'RETURN1')
 check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1')
 
 -- basic 'for' loops